Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

introduced RenderWithOptions method, changed RenderTo signature; modi… #97

Merged
merged 1 commit into from
Dec 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 37 additions & 10 deletions elem.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,16 +53,22 @@ var booleanAttrs = map[string]struct{}{
attrs.Selected: {},
}

type RenderOptions struct {
// DisableHtmlPreamble disables the doctype preamble for the HTML tag if it exists in the rendering tree
DisableHtmlPreamble bool
}

type Node interface {
RenderTo(builder *strings.Builder)
RenderTo(builder *strings.Builder, opts RenderOptions)
Render() string
RenderWithOptions(opts RenderOptions) string
}

// NoneNode represents a node that renders nothing.
type NoneNode struct{}

// RenderTo for NoneNode does nothing.
func (n NoneNode) RenderTo(builder *strings.Builder) {
func (n NoneNode) RenderTo(builder *strings.Builder, opts RenderOptions) {
// Intentionally left blank to render nothing
}

Expand All @@ -71,37 +77,54 @@ func (n NoneNode) Render() string {
return ""
}

// RenderWithOptions for NoneNode returns an empty string.
func (n NoneNode) RenderWithOptions(opts RenderOptions) string {
return ""
}

type TextNode string

func (t TextNode) RenderTo(builder *strings.Builder) {
func (t TextNode) RenderTo(builder *strings.Builder, opts RenderOptions) {
builder.WriteString(string(t))
}

func (t TextNode) Render() string {
return string(t)
}

func (t TextNode) RenderWithOptions(opts RenderOptions) string {
return string(t)
}

type RawNode string

func (r RawNode) RenderTo(builder *strings.Builder) {
func (r RawNode) RenderTo(builder *strings.Builder, opts RenderOptions) {
builder.WriteString(string(r))
}

func (r RawNode) Render() string {
return string(r)
}

func (t RawNode) RenderWithOptions(opts RenderOptions) string {
return string(t)
}

type CommentNode string

func (c CommentNode) RenderTo(builder *strings.Builder) {
func (c CommentNode) RenderTo(builder *strings.Builder, opts RenderOptions) {
builder.WriteString("<!-- ")
builder.WriteString(string(c))
builder.WriteString(" -->")
}

func (c CommentNode) Render() string {
return c.RenderWithOptions(RenderOptions{})
}

func (c CommentNode) RenderWithOptions(opts RenderOptions) string {
var builder strings.Builder
c.RenderTo(&builder)
c.RenderTo(&builder, opts)
return builder.String()
}

Expand All @@ -111,11 +134,11 @@ type Element struct {
Children []Node
}

func (e *Element) RenderTo(builder *strings.Builder) {
func (e *Element) RenderTo(builder *strings.Builder, opts RenderOptions) {
// The HTML tag needs a doctype preamble in order to ensure
// browsers don't render in legacy/quirks mode
// https://developer.mozilla.org/en-US/docs/Glossary/Doctype
if e.Tag == "html" {
if !opts.DisableHtmlPreamble && e.Tag == "html" {
builder.WriteString("<!DOCTYPE html>")
}

Expand Down Expand Up @@ -146,7 +169,7 @@ func (e *Element) RenderTo(builder *strings.Builder) {

// Build the content
for _, child := range e.Children {
child.RenderTo(builder)
child.RenderTo(builder, opts)
}

// Append closing tag
Expand Down Expand Up @@ -174,8 +197,12 @@ func (e *Element) renderAttrTo(attrName string, builder *strings.Builder) {
}

func (e *Element) Render() string {
return e.RenderWithOptions(RenderOptions{})
}

func (e *Element) RenderWithOptions(opts RenderOptions) string {
var builder strings.Builder
e.RenderTo(&builder)
e.RenderTo(&builder, opts)
return builder.String()
}

Expand Down
16 changes: 13 additions & 3 deletions elements_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ package elem
import (
"testing"

"github.com/chasefleming/elem-go/styles"

"github.com/chasefleming/elem-go/attrs"
"github.com/stretchr/testify/assert"
)
Expand All @@ -29,6 +27,18 @@ func TestHtml(t *testing.T) {
assert.Equal(t, expected, el.Render())
}

func TestHtmlWithOptions(t *testing.T) {
expected := `<html lang="en"><head><meta charset="UTF-8"><title>Elem Page</title></head><body><p>Welcome to Elem!</p></body></html>`
el := Html(attrs.Props{attrs.Lang: "en"},
Head(nil,
Meta(attrs.Props{attrs.Charset: "UTF-8"}),
Title(nil, Text("Elem Page")),
),
Body(nil, P(nil, Text("Welcome to Elem!"))),
)
assert.Equal(t, expected, el.RenderWithOptions(RenderOptions{DisableHtmlPreamble: true}))
}

// ========== Text Formatting and Structure ==========

func TestA(t *testing.T) {
Expand Down Expand Up @@ -269,7 +279,7 @@ func TestScript(t *testing.T) {
func TestStyle(t *testing.T) {
expected := `<style type="text/css">.test-class {color: #333;}</style>`
cssContent := `.test-class {color: #333;}`
el := Style(attrs.Props{attrs.Type: "text/css"}, styles.CSS(cssContent))
el := Style(attrs.Props{attrs.Type: "text/css"}, TextNode(cssContent))
assert.Equal(t, expected, el.Render())
}

Expand Down
4 changes: 3 additions & 1 deletion styles/styles.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package styles
import (
"sort"
"strings"

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

// Props is a map of CSS properties
Expand Down Expand Up @@ -38,7 +40,7 @@ func (p Props) ToInline() string {
type CSSNode string

// RenderTo satisfies part of the Node interface by allowing CSSNode to be written to a strings.Builder
func (cn CSSNode) RenderTo(builder *strings.Builder) {
func (cn CSSNode) RenderTo(builder *strings.Builder, opts elem.RenderOptions) {
builder.WriteString(string(cn))
}

Expand Down
11 changes: 10 additions & 1 deletion styles/styles_test.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
package styles

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

"github.com/stretchr/testify/assert"
)

func TestCSS(t *testing.T) {
cssContent := `.test-class {color: #333;}`
expected := `.test-class {color: #333;}`
el := CSS(cssContent)
assert.Equal(t, expected, el.Render())
}

func TestStyleToInline(t *testing.T) {
style := Props{
BackgroundColor: "blue",
Expand Down Expand Up @@ -36,3 +44,4 @@ func TestStyleString_UnorderedKeys(t *testing.T) {
}
assert.Equal(t, "background-color: blue; color: white; font-size: 16px; outline-style: solid;", style.ToInline())
}