-
Notifications
You must be signed in to change notification settings - Fork 0
/
htmlencoder.go
120 lines (110 loc) · 1.99 KB
/
htmlencoder.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
package web
import (
"io"
"github.com/gregoryv/nexus"
)
func NewHtmlEncoder(w io.Writer) *HtmlEncoder {
p, err := nexus.NewPrinter(w)
return &HtmlEncoder{
Printer: p,
err: err,
}
}
type HtmlEncoder struct {
*nexus.Printer
err *error
}
func (p *HtmlEncoder) Encode(t interface{}) error {
if t, ok := t.(*Element); ok && t.Name == "html" {
p.Print("<!DOCTYPE html>\n\n")
}
p.writeElement(t)
return *p.err
}
func (p *HtmlEncoder) writeElement(t interface{}) {
switch t := t.(type) {
case *Element:
if t.Name != "wrapper" {
p.open(t)
}
for _, child := range t.Children {
p.writeElement(child)
}
if t.Name != "wrapper" {
p.close(t)
}
case io.Reader:
io.Copy(p, t)
case io.WriterTo:
t.WriteTo(p)
default:
p.Printf("%v", t)
}
}
var newLineAfterOpen = map[string]bool{
"html": true,
"body": true,
"head": true,
"table": true,
"article": true,
"section": true,
"ol": true,
"ul": true,
"dl": true,
"fieldset": true,
}
func (p *HtmlEncoder) open(t *Element) {
p.Print("<", t.Name)
for _, Attributes := range t.Attributes {
p.Print(" ", Attributes.String())
}
if !t.simple {
p.Print(">")
}
if newLineAfterOpen[t.Name] {
p.Println()
}
}
var newLineAfterClose = map[string]bool{
"html": true,
"body": true,
"head": true,
"title": true,
"table": true,
"tr": true,
"article": true,
"header": true,
"nav": true,
"section": true,
"style": true,
"script": true,
"meta": true,
"link": true,
"p": true,
"h1": true,
"h2": true,
"h3": true,
"h4": true,
"h5": true,
"h6": true,
"li": true,
"ul": true,
"ol": true,
"dt": true,
"dd": true,
"div": true,
"fieldset": true,
}
func (p *HtmlEncoder) close(t *Element) {
if t.simple {
p.Print("/>")
if newLineAfterClose[t.Name] {
p.Println()
}
return
}
p.Print("</", t.Name, ">")
if newLineAfterClose[t.Name] {
p.Println()
}
}