Skip to content

Commit

Permalink
Merge pull request #49 from whisk/main
Browse files Browse the repository at this point in the history
added support for boolean attributes #48
  • Loading branch information
chasefleming authored Nov 1, 2023
2 parents 717ccf0 + be0ff9f commit a802822
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 5 deletions.
40 changes: 35 additions & 5 deletions elem.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package elem
import (
"sort"
"strings"

"github.com/chasefleming/elem-go/attrs"
)

// List of HTML5 void elements. Void elements, also known as self-closing or empty elements,
Expand All @@ -27,6 +29,20 @@ var voidElements = map[string]struct{}{
"wbr": {},
}

// List of boolean attributes. Boolean attributes can't have literal values. The presence of an boolean
// attribute represents the "true" value. To represent the "false" value, the attribute has to be omitted.
// See https://html.spec.whatwg.org/multipage/indices.html#attributes-3 for reference
var booleanAttrs = map[string]struct{}{
attrs.Async: {},
attrs.Autofocus: {},
attrs.Checked: {},
attrs.Defer: {},
attrs.Disabled: {},
attrs.Multiple: {},
attrs.Readonly: {},
attrs.Required: {},
}

type Attrs map[string]string

type Node interface {
Expand Down Expand Up @@ -64,11 +80,7 @@ func (e *Element) RenderTo(builder *strings.Builder) {

// Append the attributes to the builder
for _, k := range keys {
builder.WriteString(` `)
builder.WriteString(k)
builder.WriteString(`="`)
builder.WriteString(e.Attrs[k])
builder.WriteString(`"`)
e.renderAttrTo(k, builder)
}

// If it's a void element, close it and return
Expand All @@ -91,6 +103,24 @@ func (e *Element) RenderTo(builder *strings.Builder) {
builder.WriteString(`>`)
}

// return string representation of given attribute with its value
func (e *Element) renderAttrTo(attrName string, builder *strings.Builder) {
if _, exists := booleanAttrs[attrName]; exists {
// boolean attribute presents its name only if the value is "true"
if e.Attrs[attrName] == "true" {
builder.WriteString(` `)
builder.WriteString(attrName)
}
} else {
// regular attribute has a name and a value
builder.WriteString(` `)
builder.WriteString(attrName)
builder.WriteString(`="`)
builder.WriteString(e.Attrs[attrName])
builder.WriteString(`"`)
}
}

func (e *Element) Render() string {
var builder strings.Builder
e.RenderTo(&builder)
Expand Down
19 changes: 19 additions & 0 deletions elements_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,25 @@ func TestTextarea(t *testing.T) {
assert.Equal(t, expected, el.Render())
}

// ========== Boolean attributes ==========
func TestCheckedTrue(t *testing.T) {
expected := `<input checked name="allow" type="checkbox">`
el := Input(Attrs{attrs.Type: "checkbox", attrs.Name: "allow", attrs.Checked: "true"})
assert.Equal(t, expected, el.Render())
}

func TestCheckedFalse(t *testing.T) {
expected := `<input name="allow" type="checkbox">`
el := Input(Attrs{attrs.Type: "checkbox", attrs.Name: "allow", attrs.Checked: "false"})
assert.Equal(t, expected, el.Render())
}

func TestCheckedEmpty(t *testing.T) {
expected := `<input name="allow" type="checkbox">`
el := Input(Attrs{attrs.Type: "checkbox", attrs.Name: "allow", attrs.Checked: ""})
assert.Equal(t, expected, el.Render())
}

// ========== Hyperlinks and Multimedia ==========

func TestImg(t *testing.T) {
Expand Down

0 comments on commit a802822

Please sign in to comment.