-
Notifications
You must be signed in to change notification settings - Fork 0
/
css.go
76 lines (71 loc) · 2.13 KB
/
css.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
package temple
import (
"context"
"crypto/sha256"
"encoding/hex"
"fmt"
"html/template"
)
// CSSEmbedder is an interface that Components can fulfill to include some CSS
// that should be embedded directly into the rendered HTML. The contents will
// be made available to the template as .EmbeddedCSS.
type CSSEmbedder interface {
// EmbedCSS returns the CSS, without <style> tags, that should be
// embedded directly in the output HTML.
//
// If this Component embeds any other Components, it should include
// their EmbedCSS output in its own EmbedCSS output.
EmbedCSS(context.Context) template.CSS
}
// CSSLinker is an interface that Components can fulfill to include some CSS
// that should be loaded through a <link> element in the template. The contents
// will be made available to the template as .LinkedCSS.
type CSSLinker interface {
// LinkCSS returns a list of URLs to CSS files that should be linked to
// from the output HTML.
//
// If this Component embeds any other Components, it should include
// their LinkCSS output in its own LinkCSS output.
LinkCSS(context.Context) []string
}
func getComponentCSSEmbeds(ctx context.Context, component Component) template.CSS {
var results template.CSS
seen := map[string]struct{}{}
components := getRecursiveComponents(ctx, component)
for _, comp := range components {
embed, ok := comp.(CSSEmbedder)
if !ok {
continue
}
css := embed.EmbedCSS(ctx)
checksum := hex.EncodeToString(sha256.New().Sum([]byte(css)))
if _, ok := seen[checksum]; ok {
continue
}
seen[checksum] = struct{}{}
results += template.CSS(fmt.Sprintf(`
/* embedded CSS from %T */
%s`, comp, css)) // #nosec G203
}
return results
}
func getComponentCSSLinks(ctx context.Context, component Component) []string {
var results []string
seen := map[string]struct{}{}
components := getRecursiveComponents(ctx, component)
for _, comp := range components {
link, ok := comp.(CSSLinker)
if !ok {
continue
}
css := link.LinkCSS(ctx)
for _, source := range css {
if _, ok := seen[source]; ok {
continue
}
results = append(results, source)
seen[source] = struct{}{}
}
}
return results
}