12
"xelbot.com/reprogl/container"
15
var fileHashes = make(map[string]string)
17
func cdnBase() string {
18
return container.GetConfig().CDNBaseURL
21
func assetTag(file string) template.HTML {
29
result, ok := fileHashes[file]
31
return template.HTML(result)
34
if strings.HasSuffix(file, ".css") {
35
tmpl = `<link rel="stylesheet" href="%s" integrity="%s" crossorigin="anonymous">`
36
subPath = file[:len(file)-3]
38
} else if strings.HasSuffix(file, ".js") {
39
tmpl = `<script src="%s" integrity="%s" crossorigin="anonymous"></script>`
40
subPath = file[:len(file)-2]
43
tmpl = `<unknown src="%s" integrity="%s"/>`
48
hash := subresourceIntegrity(file)
49
timeBasedPart := timeBased(file)
51
result = fmt.Sprintf(tmpl, cdnBase()+"/"+subPath+timeBasedPart+ext, hash)
52
if !container.IsDevMode() {
53
fileHashes[file] = result
56
return template.HTML(result)
59
func subresourceIntegrity(file string) string {
62
f, err := os.Open("./public/" + file)
70
bytes := make([]byte, 1024)
72
n, err = f.Read(bytes)
80
return "sha256-" + base64.StdEncoding.EncodeToString(hash.Sum(nil))
83
func timeBased(file string) string {
84
fileInfo, err := os.Stat("./public/" + file)
89
modificatedAt := fileInfo.ModTime()
93
modificatedAt.Year()%100,
94
zeroPad(modificatedAt.YearDay(), 3),
95
zeroPad(modificatedAt.Hour(), 2),
96
zeroPad(modificatedAt.Minute(), 2),
97
zeroPad(modificatedAt.Second(), 2),
101
func zeroPad(i, width int) string {
102
istring := strconv.Itoa(i)
104
return strings.Repeat("0", width-len(istring)) + istring