test rendering
This commit is contained in:
parent
2f496f4ca2
commit
73250375c9
42
Makefile
42
Makefile
@ -7,30 +7,38 @@ all: clean fmt build cover
|
|||||||
build: $(SOURCES) tags promote-to-tags
|
build: $(SOURCES) tags promote-to-tags
|
||||||
go build
|
go build
|
||||||
|
|
||||||
tags: tags/block.gen.go tags/inline.gen.go tags/void.block.gen.go tags/void.inline.gen.go tags/inlinechildren.gen.go tags/script.gen.go
|
tags: \
|
||||||
|
tag/block.gen.go \
|
||||||
|
tag/inline.gen.go \
|
||||||
|
tag/void.block.gen.go \
|
||||||
|
tag/void.inline.gen.go \
|
||||||
|
tag/inlinechildren.gen.go \
|
||||||
|
tag/script.gen.go
|
||||||
|
go fmt tag/*
|
||||||
|
|
||||||
promote-to-tags: tags/promote.gen.go
|
promote-to-tags: tag/promote.gen.go
|
||||||
|
go fmt tag/*
|
||||||
|
|
||||||
tags/block.gen.go: $(SOURCES) tags.block.txt
|
tag/block.gen.go: $(SOURCES) tag.block.txt
|
||||||
go run script/generate-tags.go < tags.block.txt > tags/block.gen.go
|
go run script/generate-tags.go < tag.block.txt > tag/block.gen.go
|
||||||
|
|
||||||
tags/inline.gen.go: $(SOURCES) tags.inline.txt
|
tag/inline.gen.go: $(SOURCES) tag.inline.txt
|
||||||
go run script/generate-tags.go Inline < tags.inline.txt > tags/inline.gen.go
|
go run script/generate-tags.go Inline < tag.inline.txt > tag/inline.gen.go
|
||||||
|
|
||||||
tags/inlinechildren.gen.go: $(SOURCES) tags.inlinechildren.txt
|
tag/inlinechildren.gen.go: $(SOURCES) tag.inlinechildren.txt
|
||||||
go run script/generate-tags.go InlineChildren < tags.inlinechildren.txt > tags/inlinechildren.gen.go
|
go run script/generate-tags.go InlineChildren < tag.inlinechildren.txt > tag/inlinechildren.gen.go
|
||||||
|
|
||||||
tags/void.block.gen.go: $(SOURCES) tags.void.block.txt
|
tag/void.block.gen.go: $(SOURCES) tag.void.block.txt
|
||||||
go run script/generate-tags.go Void < tags.void.block.txt > tags/void.block.gen.go
|
go run script/generate-tags.go Void < tag.void.block.txt > tag/void.block.gen.go
|
||||||
|
|
||||||
tags/void.inline.gen.go: $(SOURCES) tags.void.inline.txt
|
tag/void.inline.gen.go: $(SOURCES) tag.void.inline.txt
|
||||||
go run script/generate-tags.go Void Inline < tags.void.inline.txt > tags/void.inline.gen.go
|
go run script/generate-tags.go Void Inline < tag.void.inline.txt > tag/void.inline.gen.go
|
||||||
|
|
||||||
tags/script.gen.go: $(SOURCES) tags.script.txt
|
tag/script.gen.go: $(SOURCES) tag.script.txt
|
||||||
go run script/generate-tags.go ScriptContent < tags.script.txt > tags/script.gen.go
|
go run script/generate-tags.go ScriptContent < tag.script.txt > tag/script.gen.go
|
||||||
|
|
||||||
tags/promote.gen.go: $(SOURCES) promote-to-tags.txt
|
tag/promote.gen.go: $(SOURCES) promote-to-tags.txt
|
||||||
go run script/promote-to-tags.go < promote-to-tags.txt > tags/promote.gen.go
|
go run script/promote-to-tags.go < promote-to-tags.txt > tag/promote.gen.go
|
||||||
|
|
||||||
fmt: $(SOURCES) tags
|
fmt: $(SOURCES) tags
|
||||||
go fmt ./...
|
go fmt ./...
|
||||||
@ -49,4 +57,4 @@ showcover: .cover
|
|||||||
|
|
||||||
clean:
|
clean:
|
||||||
go clean
|
go clean
|
||||||
rm -f tags/*.gen.go
|
rm -f tag/*.gen.go
|
||||||
|
|||||||
12
eq.go
12
eq.go
@ -6,13 +6,17 @@ func eq2(t1, t2 Tag) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
a1, a2 := AllAttributes(t1), AllAttributes(t2)
|
a1, a2 := AllAttributes(t1), AllAttributes(t2)
|
||||||
if len(a1) != len(a2) {
|
if len(a1.names) != len(a2.names) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
for name := range a1 {
|
for i, name := range a1.names {
|
||||||
v1 := a1[name]
|
if a2.names[i] != name {
|
||||||
v2, ok := a2[name]
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
v1 := a1.values[name]
|
||||||
|
v2, ok := a2.values[name]
|
||||||
if !ok || v1 != v2 {
|
if !ok || v1 != v2 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,7 +3,7 @@ package html_test
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"code.squareroundforest.org/arpio/html"
|
"code.squareroundforest.org/arpio/html"
|
||||||
. "code.squareroundforest.org/arpio/html/tags"
|
. "code.squareroundforest.org/arpio/html/tag"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
16
indent.go
16
indent.go
@ -15,6 +15,21 @@ type indentWriter struct {
|
|||||||
err error
|
err error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func indentLen(indent string) int {
|
||||||
|
var l int
|
||||||
|
r := []rune(indent)
|
||||||
|
for _, ri := range r {
|
||||||
|
if ri == '\t' {
|
||||||
|
l += 8
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
l++
|
||||||
|
}
|
||||||
|
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
func newIndentWriter(out io.Writer, indent string) *indentWriter {
|
func newIndentWriter(out io.Writer, indent string) *indentWriter {
|
||||||
return &indentWriter{
|
return &indentWriter{
|
||||||
out: bufio.NewWriter(out),
|
out: bufio.NewWriter(out),
|
||||||
@ -66,6 +81,7 @@ func (w *indentWriter) Write(p []byte) (int, error) {
|
|||||||
|
|
||||||
if r == '\n' {
|
if r == '\n' {
|
||||||
w.write('\n')
|
w.write('\n')
|
||||||
|
w.started = true
|
||||||
w.lineStarted = false
|
w.lineStarted = false
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|||||||
68
lib.go
68
lib.go
@ -9,7 +9,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// when composing html, the Attr convenience function is recommended to construct input attributes
|
// when composing html, the Attr convenience function is recommended to construct input attributes
|
||||||
type Attributes map[string]any
|
type Attributes struct {
|
||||||
|
names []string
|
||||||
|
values map[string]any
|
||||||
|
}
|
||||||
|
|
||||||
// immutable
|
// immutable
|
||||||
// calling creates a new copy with the passed in attributes and child nodes applied only to the copy
|
// calling creates a new copy with the passed in attributes and child nodes applied only to the copy
|
||||||
@ -31,13 +34,6 @@ type Indentation struct {
|
|||||||
Indent string
|
Indent string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tag) String() string {
|
|
||||||
buf := bytes.NewBuffer(nil)
|
|
||||||
r := renderer{out: buf}
|
|
||||||
t()(r)
|
|
||||||
return buf.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
// convenience function primarily aimed to help with construction of html with tags
|
// convenience function primarily aimed to help with construction of html with tags
|
||||||
// the names and values are applied using fmt.Sprint, tolerating fmt.Stringer implementations
|
// the names and values are applied using fmt.Sprint, tolerating fmt.Stringer implementations
|
||||||
func Attr(a ...any) Attributes {
|
func Attr(a ...any) Attributes {
|
||||||
@ -45,14 +41,43 @@ func Attr(a ...any) Attributes {
|
|||||||
a = append(a, "")
|
a = append(a, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
am := make(Attributes)
|
var am Attributes
|
||||||
|
am.values = make(map[string]any)
|
||||||
for i := 0; i < len(a); i += 2 {
|
for i := 0; i < len(a); i += 2 {
|
||||||
am[fmt.Sprint(a[i])] = a[i+1]
|
name := fmt.Sprint(a[i])
|
||||||
|
am.names = append(am.names, name)
|
||||||
|
am.values[name] = a[i+1]
|
||||||
}
|
}
|
||||||
|
|
||||||
return am
|
return am
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a Attributes) Names() []string {
|
||||||
|
if len(a.names) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
n := make([]string, len(a.names))
|
||||||
|
copy(n, a.names)
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a Attributes) Has(name string) bool {
|
||||||
|
_, ok := a.values[name]
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a Attributes) Value(name string) any {
|
||||||
|
return a.values[name]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t Tag) String() string {
|
||||||
|
buf := bytes.NewBuffer(nil)
|
||||||
|
r := renderer{out: buf}
|
||||||
|
t()(r)
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
// defines a new tag with name and initial attributes and child nodes
|
// defines a new tag with name and initial attributes and child nodes
|
||||||
func Define(name string, children ...any) Tag {
|
func Define(name string, children ...any) Tag {
|
||||||
if handleQuery(name, children) {
|
if handleQuery(name, children) {
|
||||||
@ -86,7 +111,7 @@ func Doctype(children ...any) Tag {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Comment(children ...any) Tag {
|
func Comment(children ...any) Tag {
|
||||||
return Inline(Declaration(append(append([]any{"--"}, children...), "--")))
|
return Inline(Declaration(append(append([]any{"--"}, children...), "--")...))
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns the name of a tag
|
// returns the name of a tag
|
||||||
@ -100,9 +125,11 @@ func Name(t Tag) string {
|
|||||||
func AllAttributes(t Tag) Attributes {
|
func AllAttributes(t Tag) Attributes {
|
||||||
q := attributesQuery{}
|
q := attributesQuery{}
|
||||||
t()(&q)
|
t()(&q)
|
||||||
a := make(Attributes)
|
a := Attributes{values: make(map[string]any)}
|
||||||
for name, value := range q.value {
|
for _, name := range q.value.names {
|
||||||
a[name] = value
|
value := q.value.values[name]
|
||||||
|
a.names = append(a.names, name)
|
||||||
|
a.values[name] = value
|
||||||
}
|
}
|
||||||
|
|
||||||
return a
|
return a
|
||||||
@ -126,7 +153,14 @@ func DeleteAttribute(t Tag, name string) Tag {
|
|||||||
n := Name(t)
|
n := Name(t)
|
||||||
a := AllAttributes(t)
|
a := AllAttributes(t)
|
||||||
c := Children(t)
|
c := Children(t)
|
||||||
delete(a, name)
|
delete(a.values, name)
|
||||||
|
for i := range a.names {
|
||||||
|
if a.names[i] == name {
|
||||||
|
a.names = append(a.names[:i], a.names[i+1:]...)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return Define(n, append(c, a)...)
|
return Define(n, append(c, a)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,6 +208,10 @@ func Children(t Tag) []any {
|
|||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Indent() Indentation {
|
||||||
|
return Indentation{Indent: "\t"}
|
||||||
|
}
|
||||||
|
|
||||||
// renders html with t as the root node with indentation
|
// renders html with t as the root node with indentation
|
||||||
// child nodes are rendered via fmt.Sprint, tolerating fmt.Stringer implementations
|
// child nodes are rendered via fmt.Sprint, tolerating fmt.Stringer implementations
|
||||||
// consecutive spaces are considered to be so on purpose, and are converted into
|
// consecutive spaces are considered to be so on purpose, and are converted into
|
||||||
|
|||||||
@ -3,7 +3,7 @@ package html_test
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"code.squareroundforest.org/arpio/html"
|
"code.squareroundforest.org/arpio/html"
|
||||||
. "code.squareroundforest.org/arpio/html/tags"
|
. "code.squareroundforest.org/arpio/html/tag"
|
||||||
"code.squareroundforest.org/arpio/notation"
|
"code.squareroundforest.org/arpio/notation"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
@ -58,7 +58,7 @@ func TestLib(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
if err := html.RenderIndent(&b, html.Indentation{Indent: "\t"}, teamHTML(myTeam)); err != nil {
|
if err := html.RenderIndent(&b, html.Indent(), teamHTML(myTeam)); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -3,9 +3,4 @@ recommendation is not to mutate children. Ofc, creatively breaking the rules is
|
|||||||
right audience
|
right audience
|
||||||
test wrapped templates
|
test wrapped templates
|
||||||
test empty block
|
test empty block
|
||||||
escape extra space between tag boundaries
|
|
||||||
declarations: <!doctype html>
|
|
||||||
comments: <!-- foo -->
|
|
||||||
render nil as empty
|
|
||||||
support readers
|
|
||||||
review which tags should be of type inline-children
|
review which tags should be of type inline-children
|
||||||
|
|||||||
11
query.go
11
query.go
@ -53,13 +53,14 @@ func groupChildren(c []any) ([]Attributes, []any, []renderGuide) {
|
|||||||
func mergeAttributes(c []any) Attributes {
|
func mergeAttributes(c []any) Attributes {
|
||||||
a, _, _ := groupChildren(c)
|
a, _, _ := groupChildren(c)
|
||||||
if len(a) == 0 {
|
if len(a) == 0 {
|
||||||
return nil
|
return Attributes{}
|
||||||
}
|
}
|
||||||
|
|
||||||
to := make(Attributes)
|
to := Attributes{values: make(map[string]any)}
|
||||||
for _, ai := range a {
|
for _, ai := range a {
|
||||||
for name, value := range ai {
|
for _, name := range ai.names {
|
||||||
to[name] = value
|
to.names = append(to.names, name)
|
||||||
|
to.values[name] = ai.values[name]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,7 +70,7 @@ func mergeAttributes(c []any) Attributes {
|
|||||||
func findAttribute(c []any, name string) (any, bool) {
|
func findAttribute(c []any, name string) (any, bool) {
|
||||||
a, _, _ := groupChildren(c)
|
a, _, _ := groupChildren(c)
|
||||||
for i := len(a) - 1; i >= 0; i-- {
|
for i := len(a) - 1; i >= 0; i-- {
|
||||||
value, ok := a[i][name]
|
value, ok := a[i].values[name]
|
||||||
if ok {
|
if ok {
|
||||||
return value, true
|
return value, true
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,7 +3,7 @@ package html_test
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"code.squareroundforest.org/arpio/html"
|
"code.squareroundforest.org/arpio/html"
|
||||||
. "code.squareroundforest.org/arpio/html/tags"
|
. "code.squareroundforest.org/arpio/html/tag"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -11,7 +11,7 @@ func TestQuery(t *testing.T) {
|
|||||||
t.Run("group children", func(t *testing.T) {
|
t.Run("group children", func(t *testing.T) {
|
||||||
inlineDiv := html.Inline(Div(Attr("foo", "bar"), "baz"))
|
inlineDiv := html.Inline(Div(Attr("foo", "bar"), "baz"))
|
||||||
attr := html.AllAttributes(inlineDiv)
|
attr := html.AllAttributes(inlineDiv)
|
||||||
if len(attr) != 1 || attr["foo"] != "bar" {
|
if len(attr.Names()) != 1 || attr.Value("foo") != "bar" {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,7 +35,7 @@ func TestQuery(t *testing.T) {
|
|||||||
t.Run("has attributes", func(t *testing.T) {
|
t.Run("has attributes", func(t *testing.T) {
|
||||||
div := Div(Attr("foo", "bar"))
|
div := Div(Attr("foo", "bar"))
|
||||||
attr := html.AllAttributes(div)
|
attr := html.AllAttributes(div)
|
||||||
if len(attr) != 1 || attr["foo"] != "bar" {
|
if len(attr.Names()) != 1 || attr.Value("foo") != "bar" {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -43,7 +43,7 @@ func TestQuery(t *testing.T) {
|
|||||||
t.Run("no attributes", func(t *testing.T) {
|
t.Run("no attributes", func(t *testing.T) {
|
||||||
div := Div()
|
div := Div()
|
||||||
attr := html.AllAttributes(div)
|
attr := html.AllAttributes(div)
|
||||||
if len(attr) != 0 {
|
if len(attr.Names()) != 0 {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -84,7 +84,7 @@ func TestQuery(t *testing.T) {
|
|||||||
t.Run("all attributes", func(t *testing.T) {
|
t.Run("all attributes", func(t *testing.T) {
|
||||||
div := Div(Attr("foo", "bar", "baz", "qux"))
|
div := Div(Attr("foo", "bar", "baz", "qux"))
|
||||||
attr := html.AllAttributes(div)
|
attr := html.AllAttributes(div)
|
||||||
if len(attr) != 2 || attr["foo"] != "bar" || attr["baz"] != "qux" {
|
if len(attr.Names()) != 2 || attr.Value("foo") != "bar" || attr.Value("baz") != "qux" {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -109,7 +109,7 @@ func TestQuery(t *testing.T) {
|
|||||||
div := Div(Span("foo"))
|
div := Div(Span("foo"))
|
||||||
|
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
if err := html.RenderIndent(&b, html.Indentation{Indent: "\t"}, div); err != nil {
|
if err := html.RenderIndent(&b, html.Indent(), div); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
34
render.go
34
render.go
@ -3,6 +3,7 @@ package html
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
const defaultPWidth = 112
|
const defaultPWidth = 112
|
||||||
@ -52,10 +53,24 @@ func (r *renderer) getPrintf(tagName string) func(f string, a ...any) {
|
|||||||
|
|
||||||
func (r *renderer) renderAttributes(tagName string, a []Attributes) {
|
func (r *renderer) renderAttributes(tagName string, a []Attributes) {
|
||||||
printf := r.getPrintf(tagName)
|
printf := r.getPrintf(tagName)
|
||||||
|
isDeclaration := strings.HasPrefix(tagName, "!")
|
||||||
for _, ai := range a {
|
for _, ai := range a {
|
||||||
for name, value := range ai {
|
for _, name := range ai.names {
|
||||||
if isTrue, _ := value.(bool); isTrue {
|
value := ai.values[name]
|
||||||
printf(" &s", name)
|
isTrue, _ := value.(bool)
|
||||||
|
if isTrue && isDeclaration {
|
||||||
|
escaped := attributeEscape(name)
|
||||||
|
if escaped == name {
|
||||||
|
printf(" %s", name)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
printf(" \"%s\"", escaped)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if isTrue {
|
||||||
|
printf(" %s", name)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,7 +106,7 @@ func (r *renderer) renderUnindented(name string, rg renderGuide, a []Attributes,
|
|||||||
|
|
||||||
ew := newEscapeWriter(r.out)
|
ew := newEscapeWriter(r.out)
|
||||||
_, r.err = io.Copy(ew, rd)
|
_, r.err = io.Copy(ew, rd)
|
||||||
if r.err != nil {
|
if r.err == nil {
|
||||||
ew.Flush()
|
ew.Flush()
|
||||||
r.err = ew.err
|
r.err = ew.err
|
||||||
}
|
}
|
||||||
@ -165,7 +180,6 @@ func (r *renderer) renderInline(name string, rg renderGuide, a []Attributes, chi
|
|||||||
if r.err == nil {
|
if r.err == nil {
|
||||||
iw := newIndentWriter(r.out, r.currentIndent+r.indent.Indent)
|
iw := newIndentWriter(r.out, r.currentIndent+r.indent.Indent)
|
||||||
iw.Write([]byte{'\n'})
|
iw.Write([]byte{'\n'})
|
||||||
iw.Write([]byte(r.currentIndent + r.indent.Indent))
|
|
||||||
_, r.err = io.Copy(iw, rd)
|
_, r.err = io.Copy(iw, rd)
|
||||||
if r.err == nil {
|
if r.err == nil {
|
||||||
iw.Flush()
|
iw.Flush()
|
||||||
@ -222,7 +236,6 @@ func (r *renderer) renderInline(name string, rg renderGuide, a []Attributes, chi
|
|||||||
if r.err == nil {
|
if r.err == nil {
|
||||||
iw := newIndentWriter(r.out, r.currentIndent+r.indent.Indent)
|
iw := newIndentWriter(r.out, r.currentIndent+r.indent.Indent)
|
||||||
iw.Write([]byte{'\n'})
|
iw.Write([]byte{'\n'})
|
||||||
iw.Write([]byte(r.currentIndent + r.indent.Indent))
|
|
||||||
iw.Write([]byte(s))
|
iw.Write([]byte(s))
|
||||||
iw.Flush()
|
iw.Flush()
|
||||||
r.err = iw.err
|
r.err = iw.err
|
||||||
@ -298,7 +311,7 @@ func (r *renderer) renderInline(name string, rg renderGuide, a []Attributes, chi
|
|||||||
cr := new(renderer)
|
cr := new(renderer)
|
||||||
*cr = *r
|
*cr = *r
|
||||||
cr.currentIndent += cr.indent.Indent
|
cr.currentIndent += cr.indent.Indent
|
||||||
cr.pwidth -= len([]rune(cr.indent.Indent))
|
cr.pwidth -= indentLen(cr.indent.Indent)
|
||||||
if cr.pwidth < cr.indent.MinPWidth {
|
if cr.pwidth < cr.indent.MinPWidth {
|
||||||
cr.pwidth = cr.indent.MinPWidth
|
cr.pwidth = cr.indent.MinPWidth
|
||||||
}
|
}
|
||||||
@ -339,7 +352,7 @@ func (r *renderer) renderBlock(name string, rg renderGuide, a []Attributes, chil
|
|||||||
lastBlock := true
|
lastBlock := true
|
||||||
originalIndent, originalWidth := r.currentIndent, r.pwidth
|
originalIndent, originalWidth := r.currentIndent, r.pwidth
|
||||||
r.currentIndent += r.indent.Indent
|
r.currentIndent += r.indent.Indent
|
||||||
r.pwidth -= len([]rune(r.indent.Indent))
|
r.pwidth -= indentLen(r.indent.Indent)
|
||||||
if r.pwidth < r.indent.MinPWidth {
|
if r.pwidth < r.indent.MinPWidth {
|
||||||
r.pwidth = r.indent.MinPWidth
|
r.pwidth = r.indent.MinPWidth
|
||||||
}
|
}
|
||||||
@ -348,11 +361,9 @@ func (r *renderer) renderBlock(name string, rg renderGuide, a []Attributes, chil
|
|||||||
rd, isReader := c.(io.Reader)
|
rd, isReader := c.(io.Reader)
|
||||||
if isReader && rg.verbatim {
|
if isReader && rg.verbatim {
|
||||||
r.clearWrapper()
|
r.clearWrapper()
|
||||||
printf("\n")
|
|
||||||
if r.err == nil {
|
if r.err == nil {
|
||||||
iw := newIndentWriter(r.out, r.currentIndent+r.indent.Indent)
|
iw := newIndentWriter(r.out, r.currentIndent)
|
||||||
iw.Write([]byte{'\n'})
|
iw.Write([]byte{'\n'})
|
||||||
iw.Write([]byte(r.currentIndent + r.indent.Indent))
|
|
||||||
_, r.err = io.Copy(iw, rd)
|
_, r.err = io.Copy(iw, rd)
|
||||||
if r.err == nil {
|
if r.err == nil {
|
||||||
iw.Flush()
|
iw.Flush()
|
||||||
@ -406,7 +417,6 @@ func (r *renderer) renderBlock(name string, rg renderGuide, a []Attributes, chil
|
|||||||
if r.err == nil {
|
if r.err == nil {
|
||||||
iw := newIndentWriter(r.out, r.currentIndent)
|
iw := newIndentWriter(r.out, r.currentIndent)
|
||||||
iw.Write([]byte{'\n'})
|
iw.Write([]byte{'\n'})
|
||||||
iw.Write([]byte(r.currentIndent + r.indent.Indent))
|
|
||||||
iw.Write([]byte(s))
|
iw.Write([]byte(s))
|
||||||
iw.Flush()
|
iw.Flush()
|
||||||
r.err = iw.err
|
r.err = iw.err
|
||||||
|
|||||||
890
render_test.go
890
render_test.go
@ -3,36 +3,18 @@ package html_test
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"code.squareroundforest.org/arpio/html"
|
"code.squareroundforest.org/arpio/html"
|
||||||
. "code.squareroundforest.org/arpio/html/tags"
|
. "code.squareroundforest.org/arpio/html/tag"
|
||||||
"errors"
|
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
type failingWriter struct {
|
|
||||||
after int
|
|
||||||
}
|
|
||||||
|
|
||||||
func failWriteAfter(n int) *failingWriter {
|
|
||||||
return &failingWriter{n}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *failingWriter) Write(p []byte) (int, error) {
|
|
||||||
w.after -= len(p)
|
|
||||||
if w.after < 0 {
|
|
||||||
return len(p) + w.after, errors.New("test error")
|
|
||||||
}
|
|
||||||
|
|
||||||
return len(p), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRender(t *testing.T) {
|
func TestRender(t *testing.T) {
|
||||||
t.Run("merge render guides", func(t *testing.T) {
|
t.Run("merge render guides", func(t *testing.T) {
|
||||||
foo := html.Inline(html.Verbatim(Define("foo")))
|
foo := html.Inline(html.Verbatim(Define("foo")))
|
||||||
foo = foo("<bar><baz></bar>")
|
foo = foo("<bar><baz></bar>")
|
||||||
|
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
if err := html.RenderIndent(&b, html.Indentation{Indent: "\t"}, foo); err != nil {
|
if err := html.RenderIndent(&b, html.Indent(), foo); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,7 +23,8 @@ func TestRender(t *testing.T) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("attribute escaping", func(t *testing.T) {
|
t.Run("attributes", func(t *testing.T) {
|
||||||
|
t.Run("escaping", func(t *testing.T) {
|
||||||
span := Span(Attr("foo", "bar=\"&\""))
|
span := Span(Attr("foo", "bar=\"&\""))
|
||||||
|
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
@ -54,6 +37,33 @@ func TestRender(t *testing.T) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("true form", func(t *testing.T) {
|
||||||
|
span := Span(Attr("foo", true))
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.Render(&b, span); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<span foo></span>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("declaration", func(t *testing.T) {
|
||||||
|
comment := Comment("foo & bar & baz", "qux")
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.Render(&b, comment); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<!-- \"foo & bar & baz\" qux -->" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
t.Run("html escape", func(t *testing.T) {
|
t.Run("html escape", func(t *testing.T) {
|
||||||
t.Run("basic escape", func(t *testing.T) {
|
t.Run("basic escape", func(t *testing.T) {
|
||||||
span := Span("<foo>bar&baz</foo>")
|
span := Span("<foo>bar&baz</foo>")
|
||||||
@ -85,32 +95,32 @@ func TestRender(t *testing.T) {
|
|||||||
t.Run("write error", func(t *testing.T) {
|
t.Run("write error", func(t *testing.T) {
|
||||||
t.Run("fail immediately", func(t *testing.T) {
|
t.Run("fail immediately", func(t *testing.T) {
|
||||||
div := Div(Span("foo"))
|
div := Div(Span("foo"))
|
||||||
w := failWriteAfter(0)
|
w := &errorWriter{}
|
||||||
if err := html.Render(w, div); err == nil || !strings.Contains(err.Error(), "test error") {
|
if err := html.Render(w, div); err == nil || !strings.Contains(err.Error(), "test write error") {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("fail in tag", func(t *testing.T) {
|
t.Run("fail in tag", func(t *testing.T) {
|
||||||
div := Div(Span("foo"))
|
div := Div(Span("foo"))
|
||||||
w := failWriteAfter(6)
|
w := &errorWriter{failAfter: 6}
|
||||||
if err := html.Render(w, div); err == nil || !strings.Contains(err.Error(), "test error") {
|
if err := html.Render(w, div); err == nil || !strings.Contains(err.Error(), "test write error") {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("partial text children", func(t *testing.T) {
|
t.Run("partial text children", func(t *testing.T) {
|
||||||
div := Div("foo", Div("bar"), "baz")
|
div := Div("foo", Div("bar"), "baz")
|
||||||
w := failWriteAfter(5)
|
w := &errorWriter{failAfter: 5}
|
||||||
if err := html.RenderIndent(w, html.Indentation{Indent: "\t"}, div); err == nil || !strings.Contains(err.Error(), "test error") {
|
if err := html.RenderIndent(w, html.Indent(), div); err == nil || !strings.Contains(err.Error(), "test write error") {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("text children", func(t *testing.T) {
|
t.Run("text children", func(t *testing.T) {
|
||||||
div := Div("foo", "bar", "baz")
|
div := Div("foo", "bar", "baz")
|
||||||
w := failWriteAfter(5)
|
w := &errorWriter{failAfter: 5}
|
||||||
if err := html.RenderIndent(w, html.Indentation{Indent: "\t"}, div); err == nil || !strings.Contains(err.Error(), "test error") {
|
if err := html.RenderIndent(w, html.Indent(), div); err == nil || !strings.Contains(err.Error(), "test write error") {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -121,7 +131,7 @@ func TestRender(t *testing.T) {
|
|||||||
div := Div(Span("foo"))
|
div := Div(Span("foo"))
|
||||||
|
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
if err := html.RenderIndent(&b, html.Indentation{Indent: "\t"}, div); err != nil {
|
if err := html.RenderIndent(&b, html.Indent(), div); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,10 +141,10 @@ func TestRender(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("empty tag", func(t *testing.T) {
|
t.Run("empty tag", func(t *testing.T) {
|
||||||
div := Div(Br())
|
div := Div(Br)
|
||||||
|
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
if err := html.RenderIndent(&b, html.Indentation{Indent: "\t"}, div); err != nil {
|
if err := html.RenderIndent(&b, html.Indent(), div); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,7 +157,7 @@ func TestRender(t *testing.T) {
|
|||||||
div := Div("foo bar baz", Div("qux quux"), "corge")
|
div := Div("foo bar baz", Div("qux quux"), "corge")
|
||||||
|
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
if err := html.RenderIndent(&b, html.Indentation{Indent: "\t"}, div); err != nil {
|
if err := html.RenderIndent(&b, html.Indent(), div); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,13 +170,823 @@ func TestRender(t *testing.T) {
|
|||||||
div := Div(Span("foo bar baz", Div("qux quux"), "corge"))
|
div := Div(Span("foo bar baz", Div("qux quux"), "corge"))
|
||||||
|
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
if err := html.RenderIndent(&b, html.Indentation{Indent: "XYZ"}, div); err != nil {
|
if err := html.RenderIndent(&b, html.Indent(), div); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if b.String() != "<div>\nXYZ<span>foo bar baz\nXYZXYZ<div>\nXYZXYZXYZqux quux\nXYZXYZ</div>\nXYZcorge</span>\n</div>" {
|
if b.String() != "<div>\n\t<span>foo bar baz\n\t\t<div>\n\t\t\tqux quux\n\t\t</div>\n\tcorge</span>\n</div>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("verbatim", func(t *testing.T) {
|
||||||
|
foo := html.Verbatim(Define("foo"))
|
||||||
|
foo = foo("bar\nbaz\nqux")
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.RenderIndent(&b, html.Indent(), foo); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<foo>\n\tbar\n\tbaz\n\tqux\n</foo>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("script not indented", func(t *testing.T) {
|
||||||
|
script := Div(Script("foo()\nbar()\nbaz()"))
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.RenderIndent(&b, html.Indent(), script); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<div>\n\t<script>\nfoo()\nbar()\nbaz()\n\t</script>\n</div>" {
|
||||||
t.Fatal(b.String())
|
t.Fatal(b.String())
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("simple", func(t *testing.T) {
|
||||||
|
t.Run("unindented", func(t *testing.T) {
|
||||||
|
div := Div("foo")
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.Render(&b, div); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<div>foo</div>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("unindented number", func(t *testing.T) {
|
||||||
|
div := Div(42)
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.Render(&b, div); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<div>42</div>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("unindented after block", func(t *testing.T) {
|
||||||
|
div := Div(Div, "foo")
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.Render(&b, div); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<div><div></div>foo</div>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("unindented after inline", func(t *testing.T) {
|
||||||
|
div := Div(Span, "foo")
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.Render(&b, div); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<div><span></span>foo</div>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("inline", func(t *testing.T) {
|
||||||
|
span := Span("foo")
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.RenderIndent(&b, html.Indent(), span); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<span>foo</span>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("inline number", func(t *testing.T) {
|
||||||
|
span := Span(42)
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.RenderIndent(&b, html.Indent(), span); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<span>42</span>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("inline after block", func(t *testing.T) {
|
||||||
|
span := Span(Div, "foo")
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.RenderIndent(&b, html.Indent(), span); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<span>\n\t<div></div>\nfoo</span>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("inline after inline", func(t *testing.T) {
|
||||||
|
span := Span(Span, "foo")
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.RenderIndent(&b, html.Indent(), span); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<span><span></span>foo</span>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("inline tag after block", func(t *testing.T) {
|
||||||
|
span := Span(Div, Span("foo"))
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.RenderIndent(&b, html.Indent(), span); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<span>\n\t<div></div>\n<span>foo</span></span>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("inline children", func(t *testing.T) {
|
||||||
|
p := P("foo")
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.RenderIndent(&b, html.Indent(), p); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<p>foo</p>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("inline children number", func(t *testing.T) {
|
||||||
|
p := P(42)
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.RenderIndent(&b, html.Indent(), p); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<p>42</p>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("inline children after inline children", func(t *testing.T) {
|
||||||
|
p := P(P, "foo")
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.RenderIndent(&b, html.Indent(), p); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<p>\n\t<p></p>\nfoo</p>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("block", func(t *testing.T) {
|
||||||
|
div := Div("foo")
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.RenderIndent(&b, html.Indent(), div); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<div>\n\tfoo\n</div>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("block number", func(t *testing.T) {
|
||||||
|
div := Div(42)
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.RenderIndent(&b, html.Indent(), div); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<div>\n\t42\n</div>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("block after block", func(t *testing.T) {
|
||||||
|
div := Div(Div, 42)
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.RenderIndent(&b, html.Indent(), div); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<div>\n\t<div></div>\n\t42\n</div>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("block after inline", func(t *testing.T) {
|
||||||
|
div := Div(Span, 42)
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.RenderIndent(&b, html.Indent(), div); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<div>\n\t<span></span>42\n</div>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("nil child", func(t *testing.T) {
|
||||||
|
t.Run("unindented", func(t *testing.T) {
|
||||||
|
div := Div("foo", nil, "bar")
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.Render(&b, div); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<div>foobar</div>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("unindented verbatim", func(t *testing.T) {
|
||||||
|
div := html.Verbatim(Div("foo &", nil, " bar"))
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.Render(&b, div); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<div>foo & bar</div>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("unindented script", func(t *testing.T) {
|
||||||
|
script := Script("let foo =", nil, " bar && baz")
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.Render(&b, script); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<script>let foo = bar && baz</script>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("inline", func(t *testing.T) {
|
||||||
|
span := Span("foo", nil, "bar")
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.RenderIndent(&b, html.Indent(), span); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<span>foobar</span>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("inline verbatim", func(t *testing.T) {
|
||||||
|
span := html.Verbatim(Span("foo &", nil, " bar"))
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.RenderIndent(&b, html.Indent(), span); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<span>\n\tfoo &\n\t bar\n</span>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("inline script", func(t *testing.T) {
|
||||||
|
script := html.Inline(Script("let foo =", nil, " bar && baz"))
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.RenderIndent(&b, html.Indent(), script); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<script>\nlet foo =\n bar && baz\n</script>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("block", func(t *testing.T) {
|
||||||
|
div := Div("foo", nil, "bar")
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.RenderIndent(&b, html.Indent(), div); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<div>\n\tfoobar\n</div>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("block verbatim", func(t *testing.T) {
|
||||||
|
div := html.Verbatim(Div("foo &", nil, " bar"))
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.RenderIndent(&b, html.Indent(), div); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<div>\n\tfoo &\n\t bar\n</div>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("block script", func(t *testing.T) {
|
||||||
|
script := Script("let foo =", nil, " bar && baz")
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.RenderIndent(&b, html.Indent(), script); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<script>\nlet foo =\n bar && baz\n</script>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("empty child", func(t *testing.T) {
|
||||||
|
t.Run("unindented", func(t *testing.T) {
|
||||||
|
div := Div("foo", "", "bar")
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.Render(&b, div); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<div>foobar</div>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("unindented verbatim", func(t *testing.T) {
|
||||||
|
div := html.Verbatim(Div("foo &", "", " bar"))
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.Render(&b, div); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<div>foo & bar</div>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("unindented script", func(t *testing.T) {
|
||||||
|
script := Script("let foo =", "", " bar && baz")
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.Render(&b, script); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<script>let foo = bar && baz</script>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("inline", func(t *testing.T) {
|
||||||
|
span := Span("foo", "", "bar")
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.RenderIndent(&b, html.Indent(), span); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<span>foobar</span>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("inline verbatim", func(t *testing.T) {
|
||||||
|
span := html.Verbatim(Span("foo &", "", " bar"))
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.RenderIndent(&b, html.Indent(), span); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<span>\n\tfoo &\n\t bar\n</span>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("inline script", func(t *testing.T) {
|
||||||
|
script := html.Inline(Script("let foo =", "", " bar && baz"))
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.RenderIndent(&b, html.Indent(), script); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<script>\nlet foo =\n bar && baz\n</script>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("block", func(t *testing.T) {
|
||||||
|
div := Div("foo", "", "bar")
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.RenderIndent(&b, html.Indent(), div); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<div>\n\tfoobar\n</div>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("block verbatim", func(t *testing.T) {
|
||||||
|
div := html.Verbatim(Div("foo &", "", " bar"))
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.RenderIndent(&b, html.Indent(), div); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<div>\n\tfoo &\n\t bar\n</div>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("block script", func(t *testing.T) {
|
||||||
|
script := Script("let foo =", "", " bar && baz")
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.RenderIndent(&b, html.Indent(), script); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<script>\nlet foo =\n bar && baz\n</script>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("reader child", func(t *testing.T) {
|
||||||
|
t.Run("unindented", func(t *testing.T) {
|
||||||
|
rd := bytes.NewBufferString("foo & bar & baz")
|
||||||
|
div := Div(rd)
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.Render(&b, div); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<div>foo & bar & baz</div>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("unindented verbatim", func(t *testing.T) {
|
||||||
|
rd := bytes.NewBufferString("foo & bar & baz")
|
||||||
|
div := html.Verbatim(Div(rd))
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.Render(&b, div); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<div>foo & bar & baz</div>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("unindented script", func(t *testing.T) {
|
||||||
|
rd := bytes.NewBufferString("let foo = bar() && baz()")
|
||||||
|
script := Script(rd)
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.Render(&b, script); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<script>let foo = bar() && baz()</script>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("inline", func(t *testing.T) {
|
||||||
|
rd := bytes.NewBufferString("foo & bar & baz")
|
||||||
|
span := Span(rd)
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.RenderIndent(&b, html.Indent(), span); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<span>foo & bar & baz</span>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("inline verbatim", func(t *testing.T) {
|
||||||
|
rd := bytes.NewBufferString("foo & bar & baz")
|
||||||
|
span := html.Verbatim(Span(rd))
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.RenderIndent(&b, html.Indent(), span); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<span>\n\tfoo & bar & baz\n</span>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("inline script", func(t *testing.T) {
|
||||||
|
rd := bytes.NewBufferString("let foo = bar() && baz()")
|
||||||
|
script := html.Inline(Script(rd))
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.RenderIndent(&b, html.Indent(), script); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<script>\nlet foo = bar() && baz()\n</script>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("inline after block", func(t *testing.T) {
|
||||||
|
rd := bytes.NewBufferString("foo & bar & baz")
|
||||||
|
span := Span(Div, rd)
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.RenderIndent(&b, html.Indent(), span); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<span>\n\t<div></div>\nfoo & bar & baz</span>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("block", func(t *testing.T) {
|
||||||
|
rd := bytes.NewBufferString("foo & bar & baz")
|
||||||
|
div := Div(rd)
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.RenderIndent(&b, html.Indent(), div); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<div>\n\tfoo & bar & baz\n</div>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("block verbatim", func(t *testing.T) {
|
||||||
|
rd := bytes.NewBufferString("foo & bar & baz")
|
||||||
|
div := html.Verbatim(Div(rd))
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.RenderIndent(&b, html.Indent(), div); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<div>\n\tfoo & bar & baz\n</div>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("block script", func(t *testing.T) {
|
||||||
|
rd := bytes.NewBufferString("let foo = bar() && baz()")
|
||||||
|
script := Script(rd)
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.RenderIndent(&b, html.Indent(), script); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<script>\nlet foo = bar() && baz()\n</script>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("void", func(t *testing.T) {
|
||||||
|
t.Run("unindented", func(t *testing.T) {
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.Render(&b, Br); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<br>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("inline", func(t *testing.T) {
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.RenderIndent(&b, html.Indent(), Br); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<br>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("block", func(t *testing.T) {
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.RenderIndent(&b, html.Indent(), Hr); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<hr>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("no children", func(t *testing.T) {
|
||||||
|
t.Run("unindented", func(t *testing.T) {
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.Render(&b, Div); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<div></div>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("inline", func(t *testing.T) {
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.RenderIndent(&b, html.Indent(), Span); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<span></span>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("block", func(t *testing.T) {
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.RenderIndent(&b, html.Indent(), Div); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<div></div>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("verbatim", func(t *testing.T) {
|
||||||
|
t.Run("unindented", func(t *testing.T) {
|
||||||
|
div := html.Verbatim(Div("foo & bar"))
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.Render(&b, div); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<div>foo & bar</div>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("inline", func(t *testing.T) {
|
||||||
|
span := html.Verbatim(Span("foo & bar"))
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.RenderIndent(&b, html.Indent(), span); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<span>\n\tfoo & bar\n</span>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("block", func(t *testing.T) {
|
||||||
|
div := html.Verbatim(Div("foo & bar"))
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.RenderIndent(&b, html.Indent(), div); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<div>\n\tfoo & bar\n</div>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("script", func(t *testing.T) {
|
||||||
|
t.Run("unindented", func(t *testing.T) {
|
||||||
|
script := Script("let foo = bar && baz")
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.Render(&b, script); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<script>let foo = bar && baz</script>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("inline", func(t *testing.T) {
|
||||||
|
script := html.Inline(Script("let foo = bar && baz"))
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.RenderIndent(&b, html.Indent(), script); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<script>\nlet foo = bar && baz\n</script>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("block", func(t *testing.T) {
|
||||||
|
script := Script("let foo = bar && baz")
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.RenderIndent(&b, html.Indent(), script); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<script>\nlet foo = bar && baz\n</script>" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("wrap", func(t *testing.T) {
|
||||||
|
t.Run("simple", func(t *testing.T) {
|
||||||
|
p := P("foo bar baz qux quux corge")
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.RenderIndent(&b, html.Indentation{Indent: "\t", PWidth: 15}, p); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<p>foo bar baz\nqux quux corge\n</p>" {
|
||||||
|
t.Error(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("min width", func(t *testing.T) {
|
||||||
|
div := Div(P("foo bar baz qux quux corge"))
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.RenderIndent(&b, html.Indentation{Indent: "\t", PWidth: 21, MinPWidth: 18}, div); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<div>\n\t<p>foo bar baz qux\n\tquux corge</p>\n</div>" {
|
||||||
|
t.Error(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("min width inline", func(t *testing.T) {
|
||||||
|
span := Span(P("foo bar baz qux quux corge"))
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := html.RenderIndent(&b, html.Indentation{Indent: "\t", PWidth: 21, MinPWidth: 18}, span); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "<span>\n\t<p>foo bar baz qux\n\tquux corge</p>\n</span>" {
|
||||||
|
t.Error(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -47,7 +47,7 @@ func main() {
|
|||||||
|
|
||||||
printf("// generated by ../script/generate-tags.go\n")
|
printf("// generated by ../script/generate-tags.go\n")
|
||||||
printf("\n")
|
printf("\n")
|
||||||
printf("package tags\n")
|
printf("package tag\n")
|
||||||
printf("import \"code.squareroundforest.org/arpio/html\"\n")
|
printf("import \"code.squareroundforest.org/arpio/html\"\n")
|
||||||
for _, si := range ss {
|
for _, si := range ss {
|
||||||
exp := fmt.Sprintf("html.Define(\"%s\")", si)
|
exp := fmt.Sprintf("html.Define(\"%s\")", si)
|
||||||
|
|||||||
@ -46,7 +46,7 @@ func main() {
|
|||||||
|
|
||||||
printf("// generated by ../script/promote-to-tags.go\n")
|
printf("// generated by ../script/promote-to-tags.go\n")
|
||||||
printf("\n")
|
printf("\n")
|
||||||
printf("package tags\n")
|
printf("package tag\n")
|
||||||
printf("import \"code.squareroundforest.org/arpio/html\"\n")
|
printf("import \"code.squareroundforest.org/arpio/html\"\n")
|
||||||
for _, si := range ss {
|
for _, si := range ss {
|
||||||
printf("var %s = html.%s\n", si, si)
|
printf("var %s = html.%s\n", si, si)
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
// generated by ../script/generate-tags.go
|
// generated by ../script/generate-tags.go
|
||||||
|
|
||||||
package tags
|
package tag
|
||||||
|
|
||||||
import "code.squareroundforest.org/arpio/html"
|
import "code.squareroundforest.org/arpio/html"
|
||||||
|
|
||||||
@ -1,6 +1,6 @@
|
|||||||
// generated by ../script/generate-tags.go
|
// generated by ../script/generate-tags.go
|
||||||
|
|
||||||
package tags
|
package tag
|
||||||
|
|
||||||
import "code.squareroundforest.org/arpio/html"
|
import "code.squareroundforest.org/arpio/html"
|
||||||
|
|
||||||
@ -1,6 +1,6 @@
|
|||||||
// generated by ../script/generate-tags.go
|
// generated by ../script/generate-tags.go
|
||||||
|
|
||||||
package tags
|
package tag
|
||||||
|
|
||||||
import "code.squareroundforest.org/arpio/html"
|
import "code.squareroundforest.org/arpio/html"
|
||||||
|
|
||||||
@ -1,6 +1,6 @@
|
|||||||
// generated by ../script/promote-to-tags.go
|
// generated by ../script/promote-to-tags.go
|
||||||
|
|
||||||
package tags
|
package tag
|
||||||
|
|
||||||
import "code.squareroundforest.org/arpio/html"
|
import "code.squareroundforest.org/arpio/html"
|
||||||
|
|
||||||
@ -1,6 +1,6 @@
|
|||||||
// generated by ../script/generate-tags.go
|
// generated by ../script/generate-tags.go
|
||||||
|
|
||||||
package tags
|
package tag
|
||||||
|
|
||||||
import "code.squareroundforest.org/arpio/html"
|
import "code.squareroundforest.org/arpio/html"
|
||||||
|
|
||||||
@ -1,6 +1,6 @@
|
|||||||
// generated by ../script/generate-tags.go
|
// generated by ../script/generate-tags.go
|
||||||
|
|
||||||
package tags
|
package tag
|
||||||
|
|
||||||
import "code.squareroundforest.org/arpio/html"
|
import "code.squareroundforest.org/arpio/html"
|
||||||
|
|
||||||
@ -1,6 +1,6 @@
|
|||||||
// generated by ../script/generate-tags.go
|
// generated by ../script/generate-tags.go
|
||||||
|
|
||||||
package tags
|
package tag
|
||||||
|
|
||||||
import "code.squareroundforest.org/arpio/html"
|
import "code.squareroundforest.org/arpio/html"
|
||||||
|
|
||||||
@ -21,6 +21,10 @@ func validateSymbol(s string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func validateTagName(name string) error {
|
func validateTagName(name string) error {
|
||||||
|
if strings.HasPrefix(name, "!") {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
return validateSymbol(name)
|
return validateSymbol(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,7 +45,7 @@ func validate(name string, children []any) error {
|
|||||||
|
|
||||||
isDeclaration := strings.HasPrefix(name, "!")
|
isDeclaration := strings.HasPrefix(name, "!")
|
||||||
for _, ai := range a {
|
for _, ai := range a {
|
||||||
for name := range ai {
|
for _, name := range ai.names {
|
||||||
if isDeclaration {
|
if isDeclaration {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,7 +3,7 @@ package html_test
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"code.squareroundforest.org/arpio/html"
|
"code.squareroundforest.org/arpio/html"
|
||||||
. "code.squareroundforest.org/arpio/html/tags"
|
. "code.squareroundforest.org/arpio/html/tag"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
3
wrap.go
3
wrap.go
@ -11,7 +11,8 @@ type wrapper struct {
|
|||||||
out *indentWriter
|
out *indentWriter
|
||||||
width int
|
width int
|
||||||
line, word *bytes.Buffer
|
line, word *bytes.Buffer
|
||||||
inWord, inTag, inSingleQuote, inQuote, lastSpace, started bool
|
inWord, inTag, inSingleQuote, inQuote bool
|
||||||
|
lastSpace, started bool
|
||||||
err error
|
err error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
10
wrap_test.go
10
wrap_test.go
@ -3,7 +3,7 @@ package html_test
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"code.squareroundforest.org/arpio/html"
|
"code.squareroundforest.org/arpio/html"
|
||||||
. "code.squareroundforest.org/arpio/html/tags"
|
. "code.squareroundforest.org/arpio/html/tag"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -56,7 +56,7 @@ func TestWrap(t *testing.T) {
|
|||||||
ew := &errorWriter{}
|
ew := &errorWriter{}
|
||||||
if err := html.RenderIndent(
|
if err := html.RenderIndent(
|
||||||
ew,
|
ew,
|
||||||
html.Indentation{Indent: "\t"},
|
html.Indent(),
|
||||||
Span(Span("foo"), Span("bar"), Span("baz")),
|
Span(Span("foo"), Span("bar"), Span("baz")),
|
||||||
); err == nil {
|
); err == nil {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
@ -117,7 +117,7 @@ func TestWrap(t *testing.T) {
|
|||||||
div := Div(Span("foo bar baz qux quux corge"))
|
div := Div(Span("foo bar baz qux quux corge"))
|
||||||
|
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
if err := html.RenderIndent(&buf, html.Indentation{Indent: "\t", PWidth: 9}, div); err != nil {
|
if err := html.RenderIndent(&buf, html.Indentation{Indent: "\t", PWidth: 15}, div); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,7 +130,7 @@ func TestWrap(t *testing.T) {
|
|||||||
div := Div(Span("foo"), " ", Span("bar"))
|
div := Div(Span("foo"), " ", Span("bar"))
|
||||||
|
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
if err := html.RenderIndent(&buf, html.Indentation{Indent: "\t"}, div); err != nil {
|
if err := html.RenderIndent(&buf, html.Indent(), div); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,7 +143,7 @@ func TestWrap(t *testing.T) {
|
|||||||
div := Div("foo\nbar\tbaz")
|
div := Div("foo\nbar\tbaz")
|
||||||
|
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
if err := html.RenderIndent(&buf, html.Indentation{Indent: "\t"}, div); err != nil {
|
if err := html.RenderIndent(&buf, html.Indent(), div); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user