diff options
Diffstat (limited to 'web/utils.go')
| -rw-r--r-- | web/utils.go | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/web/utils.go b/web/utils.go new file mode 100644 index 0000000..18b5b52 --- /dev/null +++ b/web/utils.go @@ -0,0 +1,103 @@ +package web + +import ( + "fmt" + "html/template" + "net/url" + "strings" + "time" +) + +func templateFuncs() template.FuncMap { + return template.FuncMap{ + "repoURL": repoURL, + "manifestURL": manifestURL, + "pull": pullAddress, + "size": formatSize, + "timestamp": timestamp, + "age": displayAge, + "join": strings.Join, + } +} + +// sanitizeURLPath escapes each path segment separately, preserving slashes in +// names such as group/repository. Appends a trailing slash. +func sanitizeURLPath(path string) string { + parts := strings.Split(path, "/") + for i := range parts { + parts[i] = url.PathEscape(parts[i]) + } + return strings.Join(parts, "/") + "/" +} + +func repoURL(name string) string { + return "/r/" + sanitizeURLPath(name) +} + +func manifestURL(repository, digest, tag string) string { + path := repoURL(repository) + "m/" + sanitizeURLPath(digest) + if tag != "" { + path += "?" + url.Values{"tag": {tag}}.Encode() + } + return path +} + +func pullAddress(host, repository, tag, digest string) string { + address := strings.TrimSuffix(host, "/") + "/" + repository + if tag != "" { + address += ":" + tag + } + if digest != "" { + address += "@" + digest + } + return address +} + +func formatSize(value int64) string { + if value >= 1024*1024 { + return fmt.Sprintf("%.1fMB", float64(value)/(1024*1024)) + } + if value >= 1024 { + return fmt.Sprintf("%.1fKB", float64(value)/1024) + } + return fmt.Sprintf("%dB", value) +} + +func timestamp(t time.Time) string { + if t.IsZero() { + return "" + } + return t.Format(time.DateTime + " MST") +} + +func displayAge(updated time.Time, frozen string) string { + if frozen != "" { + return frozen + } + if updated.IsZero() { + return "unknown" + } + elapsed := time.Since(updated) + if elapsed < time.Minute { + return "just now" + } + for _, unit := range []struct { + duration time.Duration + label string + }{ + {365 * 24 * time.Hour, "year"}, + {30 * 24 * time.Hour, "month"}, + {24 * time.Hour, "day"}, + {time.Hour, "hour"}, + {time.Minute, "minute"}, + } { + if count := int(elapsed / unit.duration); count > 0 { + suffix := "s" + if count == 1 { + suffix = "" + } + return fmt.Sprintf("%d %s%s ago", count, unit.label, suffix) + } + } + return "just now" +} |