Skip to content

Commit

Permalink
Create initial elements
Browse files Browse the repository at this point in the history
  • Loading branch information
chasefleming committed Oct 1, 2023
0 parents commit 7aa55bb
Show file tree
Hide file tree
Showing 6 changed files with 190 additions and 0 deletions.
9 changes: 9 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.PHONY: test tidy

tidy:
@echo "Tidying up module..."
go mod tidy

test:
@echo "Running tests..."
go test ./...
49 changes: 49 additions & 0 deletions elem.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package elem

import (
"sort"
)

type Element struct {
Tag string
Props map[string]string
Children []interface{} // Can be either string (for text) or another Element
}

func NewElement(tag string, props Props, children ...interface{}) *Element {
return &Element{
Tag: tag,
Props: props,
Children: children,
}
}

func (e *Element) Render() string {
// Sort the keys for consistent order
keys := make([]string, 0, len(e.Props))
for k := range e.Props {
keys = append(keys, k)
}
sort.Strings(keys)

props := ""
for _, k := range keys {
props += ` ` + k + `="` + e.Props[k] + `"`
}

content := ""
for _, child := range e.Children {
switch c := child.(type) {
case string:
content += c
case *Element:
content += c.Render()
}
}

if content == "" {
return `<` + e.Tag + props + ` />` // Self-closing tag
}

return `<` + e.Tag + props + `>` + content + `</` + e.Tag + `>`
}
45 changes: 45 additions & 0 deletions elements.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package elem

func Div(props Props, children ...interface{}) *Element {
return NewElement("div", props, children...)
}

func H1(props Props, children ...interface{}) *Element {
return NewElement("h1", props, children...)
}

func H2(props Props, children ...interface{}) *Element {
return NewElement("h2", props, children...)
}

func H3(props Props, children ...interface{}) *Element {
return NewElement("h3", props, children...)
}

func P(props Props, children ...interface{}) *Element {
return NewElement("p", props, children...)
}

func A(props Props, children ...interface{}) *Element {
return NewElement("a", props, children...)
}

func Span(props Props, children ...interface{}) *Element {
return NewElement("span", props, children...)
}

func Ul(props Props, children ...interface{}) *Element {
return NewElement("ul", props, children...)
}

func Li(props Props, children ...interface{}) *Element {
return NewElement("li", props, children...)
}

func Img(props Props) *Element {
return NewElement("img", props)
}

func Text(content string) string {
return content
}
66 changes: 66 additions & 0 deletions elements_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package elem

import (
"github.com/stretchr/testify/assert"
"testing"
)

func TestA(t *testing.T) {
expected := `<a href="https://example.com">Visit Example</a>`
el := A(Props{Href: "https://example.com"}, Text("Visit Example"))
assert.Equal(t, expected, el.Render())
}

func TestDiv(t *testing.T) {
expected := `<div class="container">Hello, Elem!</div>`
el := Div(Props{Class: "container"}, Text("Hello, Elem!"))
assert.Equal(t, expected, el.Render())
}

func TestH1(t *testing.T) {
expected := `<h1 class="title">Hello, Elem!</h1>`
el := H1(Props{Class: "title"}, Text("Hello, Elem!"))
assert.Equal(t, expected, el.Render())
}

func TestH2(t *testing.T) {
expected := `<h2 class="subtitle">Hello, Elem!</h2>`
el := H2(Props{Class: "subtitle"}, Text("Hello, Elem!"))
assert.Equal(t, expected, el.Render())
}

func TestH3(t *testing.T) {
expected := `<h3>Hello, Elem!</h3>`
el := H3(nil, Text("Hello, Elem!"))
assert.Equal(t, expected, el.Render())
}

func TestImg(t *testing.T) {
expected := `<img alt="An image" src="image.jpg" />`
el := Img(Props{Src: "image.jpg", Alt: "An image"})
assert.Equal(t, expected, el.Render())
}

func TestLi(t *testing.T) {
expected := `<li>Item 1</li>`
el := Li(nil, Text("Item 1"))
assert.Equal(t, expected, el.Render())
}

func TestP(t *testing.T) {
expected := `<p>Hello, Elem!</p>`
el := P(nil, Text("Hello, Elem!"))
assert.Equal(t, expected, el.Render())
}

func TestSpan(t *testing.T) {
expected := `<span class="highlight">Hello, Elem!</span>`
el := Span(Props{Class: "highlight"}, Text("Hello, Elem!"))
assert.Equal(t, expected, el.Render())
}

func TestUl(t *testing.T) {
expected := `<ul><li>Item 1</li><li>Item 2</li></ul>`
el := Ul(nil, Li(nil, Text("Item 1")), Li(nil, Text("Item 2")))
assert.Equal(t, expected, el.Render())
}
11 changes: 11 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module github.com/chasefleming/elem-go

go 1.21.1

require github.com/stretchr/testify v1.8.4

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
10 changes: 10 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

0 comments on commit 7aa55bb

Please sign in to comment.