-
Notifications
You must be signed in to change notification settings - Fork 3
/
index.go
157 lines (144 loc) · 3.38 KB
/
index.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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
// SPDX-License-Identifier: GPL-3.0
// Copyright 2022 Pete Heist
package antler
import (
"context"
_ "embed"
"html/template"
"path/filepath"
"sort"
"sync"
)
// indexTemplate is the template for generating index.html files.
//
//go:embed index.html.tmpl
var indexTemplate string
// Index is a reporter that creates an index.html file for a Group.
type Index struct {
To string
GroupBy string
Title string
ExcludeFile []string
test []*Test
sync.Mutex
}
// report implements multiReporter to gather the Tests.
func (i *Index) report(ctx context.Context, work resultRW, test *Test,
data <-chan any) error {
i.Lock()
i.test = append(i.test, test)
i.Unlock()
return nil
}
// stop implements multiStopper to generate the index file.
func (i *Index) stop(work resultRW) (err error) {
t := template.New("Style")
if t, err = t.Parse(styleTemplate); err != nil {
return
}
t = t.New("Index")
if t, err = t.Parse(indexTemplate); err != nil {
return
}
w := work.Writer(i.To)
defer func() {
if e := w.Close(); e != nil && err == nil {
err = e
}
}()
var d indexTemplateData
if d, err = i.templateData(work.Paths()); err != nil {
return
}
err = t.Execute(w, d)
return
}
// templateData returns the templateData for the index template.
func (i *Index) templateData(paths pathSet) (data indexTemplateData, err error) {
data.Title = i.Title
data.GroupBy = i.GroupBy
for _, v := range i.groupValues() {
g := indexGroup{Key: i.GroupBy, Value: v}
c := make(map[string]struct{})
for _, t := range i.test {
if t.ID[i.GroupBy] != v {
continue
}
var l []indexLink
for _, p := range paths.withPrefix(t.Path).sorted() {
var x bool
if x, err = i.excludeFile(p); err != nil {
return
}
if !x {
l = append(l, indexLink{filepath.Base(p), p})
}
}
g.Test = append(g.Test, indexTest{t.ID, l})
for k := range t.ID {
c[k] = struct{}{}
}
}
delete(c, i.GroupBy)
for k := range c {
g.Column = append(g.Column, k)
}
sort.Strings(g.Column)
if i.GroupBy != "" {
g.Column = append([]string{i.GroupBy}, g.Column...)
}
data.Group = append(data.Group, g)
}
return
}
// excludeFile returns true if the base name of the given path matches any of
// the ExcludeFile patterns.
func (i *Index) excludeFile(path string) (matched bool, err error) {
b := filepath.Base(path)
for _, p := range i.ExcludeFile {
if matched, err = filepath.Match(p, b); err != nil || matched {
return
}
}
return
}
// groupValues returns the sorted, unique TestID values for the GroupBy key.
func (i *Index) groupValues() (val []string) {
g := make(map[string]struct{})
if i.GroupBy != "" {
for _, t := range i.test {
v := t.ID[i.GroupBy]
g[v] = struct{}{}
}
} else {
g[""] = struct{}{}
}
for k := range g {
val = append(val, k)
}
sort.Strings(val)
return
}
// indexTemplateData contains the data for indexTemplate execution.
type indexTemplateData struct {
Title string
Group []indexGroup
GroupBy string
}
// indexGroup contains the information for one group of Tests in the index.
type indexGroup struct {
Key string
Value string
Column []string
Test []indexTest
}
// indexTest contains the information for one Test in an indexGroup.
type indexTest struct {
ID TestID
Link []indexLink
}
// indexLink contains the information for one link in an indexTest.
type indexLink struct {
Name string
Href string
}