This repository has been archived by the owner on Jan 1, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtemplate.go
113 lines (89 loc) · 2.06 KB
/
template.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
package txtx
import (
"bytes"
"html/template"
"io"
"golang.org/x/net/html"
)
type Template struct {
indexName string
*template.Template
XTemplates template.HTML
}
func New(tmpl *template.Template, r io.Reader) (*Template, error) {
indexNode, err := html.Parse(r)
if err != nil {
return nil, err
}
xtmps := make(map[string]*html.Node)
if err := findAndRemoveTemplates(xtmps, indexNode); err != nil {
return nil, err
}
var tmp Template
var indexWithoutTemplates bytes.Buffer
if err := html.Render(&indexWithoutTemplates, indexNode); err != nil {
return nil, err
}
tmp.Template, err = tmpl.Parse(html.UnescapeString(indexWithoutTemplates.String()))
if err != nil {
return nil, err
}
for id, nd := range xtmps {
var buf bytes.Buffer
if err := html.Render(&buf, nd.FirstChild); err != nil {
return nil, err
}
t, err := tmpl.New(id).Parse(html.UnescapeString(buf.String()))
if err != nil {
return nil, err
}
if tmp.Template, err = tmp.Template.AddParseTree(id, t.Tree); err != nil {
return nil, err
}
}
for _, nd := range xtmps {
var xt bytes.Buffer
if err := html.Render(&xt, nd); err != nil {
return nil, err
}
tmp.XTemplates += "\n" + template.HTML(xt.String())
}
return &tmp, nil
}
func findAndRemoveTemplates(xtmps map[string]*html.Node, node *html.Node) error {
for ; node != nil; node = node.NextSibling {
if node.Type == html.ElementNode &&
node.Data == "script" &&
hasAttTypeXTemplate(node.Attr) {
xtmps[getID(node.Attr)] = node
if node.Parent != nil {
next := node.PrevSibling
node.Parent.RemoveChild(node)
node = next
}
continue
}
if node.FirstChild != nil {
if err := findAndRemoveTemplates(xtmps, node.FirstChild); err != nil {
return err
}
}
}
return nil
}
func hasAttTypeXTemplate(attr []html.Attribute) bool {
for _, at := range attr {
if at.Key == "type" && at.Val == "text/go-template" {
return true
}
}
return false
}
func getID(attr []html.Attribute) string {
for _, at := range attr {
if at.Key == "id" {
return at.Val
}
}
return ""
}