diff options
-rw-r--r-- | attr/attributes.go | 10 | ||||
-rw-r--r-- | attr/attributes_test.go | 12 | ||||
-rw-r--r-- | attr/boolean.go | 45 | ||||
-rw-r--r-- | attr/boolean_test.go | 32 | ||||
-rw-r--r-- | attr/form.go | 15 | ||||
-rw-r--r-- | attr/form_test.go | 16 | ||||
-rw-r--r-- | attr/simple.go | 105 | ||||
-rw-r--r-- | attr/simple_test.go | 47 | ||||
-rw-r--r-- | examples/simple/simple.go | 33 |
9 files changed, 243 insertions, 72 deletions
diff --git a/attr/attributes.go b/attr/attributes.go index 415e6f1..2b25681 100644 --- a/attr/attributes.go +++ b/attr/attributes.go @@ -9,16 +9,6 @@ import ( g "github.com/maragudk/gomponents" ) -// ID returns an attribute with name "id" and the given value. -func ID(v string) g.Node { - return g.Attr("id", v) -} - -// Class returns an attribute with name "class" and the given value. -func Class(v string) g.Node { - return g.Attr("class", v) -} - // 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. diff --git a/attr/attributes_test.go b/attr/attributes_test.go index c2ddff0..efb7044 100644 --- a/attr/attributes_test.go +++ b/attr/attributes_test.go @@ -8,18 +8,6 @@ import ( "github.com/maragudk/gomponents/attr" ) -func TestID(t *testing.T) { - t.Run("given a value, returns id=value", func(t *testing.T) { - assert.Equal(t, ` id="hat"`, attr.ID("hat")) - }) -} - -func TestClass(t *testing.T) { - t.Run("given a value, returns class=value", func(t *testing.T) { - assert.Equal(t, ` class="hat"`, attr.Class("hat")) - }) -} - 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"`, attr.Classes{ diff --git a/attr/boolean.go b/attr/boolean.go new file mode 100644 index 0000000..2a70c9d --- /dev/null +++ b/attr/boolean.go @@ -0,0 +1,45 @@ +package attr + +import ( + g "github.com/maragudk/gomponents" +) + +func Async() g.Node { + return g.Attr("async") +} + +func AutoFocus() g.Node { + return g.Attr("autofocus") +} + +func AutoPlay() g.Node { + return g.Attr("autoplay") +} + +func Controls() g.Node { + return g.Attr("controls") +} + +func Defer() g.Node { + return g.Attr("defer") +} + +func Disabled() g.Node { + return g.Attr("disabled") +} + +func Multiple() g.Node { + return g.Attr("multiple") +} + +func ReadOnly() g.Node { + return g.Attr("readonly") +} + +func Required() g.Node { + return g.Attr("required") +} + +func Selected() g.Node { + return g.Attr("selected") +} diff --git a/attr/boolean_test.go b/attr/boolean_test.go new file mode 100644 index 0000000..4e6bb37 --- /dev/null +++ b/attr/boolean_test.go @@ -0,0 +1,32 @@ +package attr_test + +import ( + "fmt" + "testing" + + g "github.com/maragudk/gomponents" + "github.com/maragudk/gomponents/assert" + "github.com/maragudk/gomponents/attr" +) + +func TestBooleanAttributes(t *testing.T) { + cases := map[string]func() g.Node{ + "async": attr.Async, + "autofocus": attr.AutoFocus, + "autoplay": attr.AutoPlay, + "controls": attr.Controls, + "defer": attr.Defer, + "disabled": attr.Disabled, + "multiple": attr.Multiple, + "readonly": attr.ReadOnly, + "required": attr.Required, + "selected": attr.Selected, + } + + for name, fn := range cases { + t.Run(fmt.Sprintf("should output %v", name), func(t *testing.T) { + n := g.El("div", fn()) + assert.Equal(t, fmt.Sprintf(`<div %v />`, name), n) + }) + } +} diff --git a/attr/form.go b/attr/form.go deleted file mode 100644 index b3eec05..0000000 --- a/attr/form.go +++ /dev/null @@ -1,15 +0,0 @@ -package attr - -import ( - g "github.com/maragudk/gomponents" -) - -// Placeholder returns an attribute with name "placeholder" and the given value. -func Placeholder(v string) g.Node { - return g.Attr("placeholder", v) -} - -// Required returns an attribute with name "required". -func Required() g.Node { - return g.Attr("required") -} diff --git a/attr/form_test.go b/attr/form_test.go deleted file mode 100644 index d222464..0000000 --- a/attr/form_test.go +++ /dev/null @@ -1,16 +0,0 @@ -package attr_test - -import ( - "testing" - - g "github.com/maragudk/gomponents" - "github.com/maragudk/gomponents/assert" - "github.com/maragudk/gomponents/attr" -) - -func TestForms(t *testing.T) { - t.Run("adds placeholder and required attributes", func(t *testing.T) { - e := g.El("input", attr.Placeholder("hat"), attr.Required()) - assert.Equal(t, `<input placeholder="hat" required />`, e) - }) -} diff --git a/attr/simple.go b/attr/simple.go new file mode 100644 index 0000000..e286c26 --- /dev/null +++ b/attr/simple.go @@ -0,0 +1,105 @@ +package attr + +import ( + g "github.com/maragudk/gomponents" +) + +func Accept(v string) g.Node { + return g.Attr("accept", v) +} + +func AutoComplete(v string) g.Node { + return g.Attr("autocomplete", v) +} + +func Class(v string) g.Node { + return g.Attr("class", v) +} + +func Form(v string) g.Node { + return g.Attr("form", v) +} + +func Height(v string) g.Node { + return g.Attr("height", v) +} + +func Href(v string) g.Node { + return g.Attr("href", v) +} + +func ID(v string) g.Node { + return g.Attr("id", v) +} + +func Lang(v string) g.Node { + return g.Attr("lang", v) +} + +func Max(v string) g.Node { + return g.Attr("max", v) +} + +func MaxLength(v string) g.Node { + return g.Attr("maxlength", v) +} + +func Min(v string) g.Node { + return g.Attr("min", v) +} + +func MinLength(v string) g.Node { + return g.Attr("minlength", v) +} + +func Name(v string) g.Node { + return g.Attr("name", v) +} + +func Pattern(v string) g.Node { + return g.Attr("pattern", v) +} + +func Preload(v string) g.Node { + return g.Attr("preload", v) +} + +func Placeholder(v string) g.Node { + return g.Attr("placeholder", v) +} + +func Rel(v string) g.Node { + return g.Attr("rel", v) +} + +func Src(v string) g.Node { + return g.Attr("src", v) +} + +func Style(v string) g.Node { + return g.Attr("style", v) +} + +func TabIndex(v string) g.Node { + return g.Attr("tabindex", v) +} + +func Target(v string) g.Node { + return g.Attr("target", v) +} + +func Title(v string) g.Node { + return g.Attr("title", v) +} + +func Type(v string) g.Node { + return g.Attr("type", v) +} + +func Value(v string) g.Node { + return g.Attr("value", v) +} + +func Width(v string) g.Node { + return g.Attr("width", v) +} diff --git a/attr/simple_test.go b/attr/simple_test.go new file mode 100644 index 0000000..784561a --- /dev/null +++ b/attr/simple_test.go @@ -0,0 +1,47 @@ +package attr_test + +import ( + "fmt" + "testing" + + g "github.com/maragudk/gomponents" + "github.com/maragudk/gomponents/assert" + "github.com/maragudk/gomponents/attr" +) + +func TestSimpleAttributes(t *testing.T) { + cases := map[string]func(string) g.Node{ + "accept": attr.Accept, + "autocomplete": attr.AutoComplete, + "class": attr.Class, + "form": attr.Form, + "height": attr.Height, + "href": attr.Href, + "id": attr.ID, + "lang": attr.Lang, + "max": attr.Max, + "maxlength": attr.MaxLength, + "min": attr.Min, + "minlength": attr.MinLength, + "name": attr.Name, + "pattern": attr.Pattern, + "preload": attr.Preload, + "placeholder": attr.Placeholder, + "rel": attr.Rel, + "src": attr.Src, + "style": attr.Style, + "tabindex": attr.TabIndex, + "target": attr.Target, + "title": attr.Title, + "type": attr.Type, + "value": attr.Value, + "width": attr.Width, + } + + for name, fn := range cases { + t.Run(fmt.Sprintf(`should output %v="hat"`, name), func(t *testing.T) { + n := g.El("div", fn("hat")) + assert.Equal(t, fmt.Sprintf(`<div %v="hat" />`, name), n) + }) + } +} diff --git a/examples/simple/simple.go b/examples/simple/simple.go index 56747e4..6683bc4 100644 --- a/examples/simple/simple.go +++ b/examples/simple/simple.go @@ -1,7 +1,6 @@ package main import ( - "fmt" "net/http" "time" @@ -11,18 +10,14 @@ import ( ) func main() { - _ = http.ListenAndServe("localhost:8080", handler()) + _ = http.ListenAndServe("localhost:8080", http.HandlerFunc(handler)) } -func handler() http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - props := pageProps{ - title: r.URL.Path, - path: r.URL.Path, - } - - _ = g.Write(w, page(props)) - } +func handler(w http.ResponseWriter, r *http.Request) { + _ = g.Write(w, page(pageProps{ + title: r.URL.Path, + path: r.URL.Path, + })) } type pageProps struct { @@ -32,11 +27,10 @@ type pageProps struct { func page(props pageProps) g.Node { return el.Document( - el.HTML( - g.Attr("lang", "en"), + el.HTML(attr.Lang("en"), el.Head( el.Title(props.title), - el.Style(g.Attr("type", "text/css"), + el.Style(attr.Type("text/css"), g.Raw(".is-active{font-weight: bold}"), g.Raw("ul.nav { list-style-type: none; margin: 0; padding: 0; overflow: hidden; }"), g.Raw("ul.nav li { display: block; padding: 8px; float: left; }"), @@ -46,8 +40,8 @@ func page(props pageProps) g.Node { navbar(navbarProps{path: props.path}), el.Hr(), el.H1(props.title), - el.P(g.Text(fmt.Sprintf("Welcome to the page at %v.", props.path))), - el.P(g.Text(fmt.Sprintf("Rendered at %v", time.Now()))), + el.P(g.Textf("Welcome to the page at %v.", props.path)), + el.P(g.Textf("Rendered at %v", time.Now())), ), ), ) @@ -68,8 +62,9 @@ func navbar(props navbarProps) g.Node { } var lis []g.Node for _, item := range items { - lis = append(lis, el.Li( - el.A(item.path, attr.Classes(map[string]bool{"is-active": props.path == item.path}), g.Text(item.text)))) + lis = append(lis, el.Li(el.A(item.path, + attr.Classes(map[string]bool{"is-active": props.path == item.path}), + g.Text(item.text)))) } - return el.Ul(append(lis, attr.Class("nav"))...) + return el.Ul(attr.Class("nav"), g.Group(lis)) } |