internal/web/funcs.go

83 lines · 2164 bytes

 1package web
 2
 3import (
 4	"fmt"
 5	"html/template"
 6	"net/url"
 7	"strconv"
 8	"strings"
 9
10	"gitbay.org/cmc/gallery/internal/library"
11	"gitbay.org/cmc/gallery/internal/render"
12)
13
14var funcs = template.FuncMap{
15	"albumURL":      albumURL,
16	"photoURL":      photoURL,
17	"imgURL":        imgURL,
18	"srcset":        srcset,
19	"preloadSrcset": preloadSrcset,
20	"ar":            aspect,
21	"exif":          exifLine,
22	"add":           func(a, b int) int { return a + b },
23}
24
25func albumURL(a *library.Album) string {
26	return "/" + url.PathEscape(a.Slug) + "/"
27}
28
29func photoURL(it *library.Item) string {
30	return "/" + url.PathEscape(it.Album) + "/" + url.PathEscape(it.Name) + "/"
31}
32
33func imgURL(it *library.Item, w int) string {
34	return fmt.Sprintf("/img/%s/%s/%d.jpg?v=%d", url.PathEscape(it.Album), url.PathEscape(it.Name), w, it.ModTime.UnixNano())
35}
36
37// srcset lists allowed widths up to the first one that reaches the source width.
38func srcset(it *library.Item) string {
39	var parts []string
40	for _, w := range render.Widths {
41		actual := w
42		reached := it.Meta.Width > 0 && w >= it.Meta.Width
43		if reached {
44			actual = it.Meta.Width
45		}
46		parts = append(parts, fmt.Sprintf("%s %dw", imgURL(it, w), actual))
47		if reached {
48			break
49		}
50	}
51	return strings.Join(parts, ", ")
52}
53
54// preloadSrcset renders the whole imagesrcset attribute: html/template treats
55// any unknown attribute containing "src" as a single URL and would escape the
56// spaces and commas a srcset list needs.
57func preloadSrcset(it *library.Item) template.HTMLAttr {
58	return template.HTMLAttr(`imagesrcset="` + template.HTMLEscapeString(srcset(it)) + `"`)
59}
60
61func aspect(it *library.Item) string {
62	if it.Meta.Height == 0 {
63		return "1"
64	}
65	return strconv.FormatFloat(float64(it.Meta.Width)/float64(it.Meta.Height), 'f', 4, 64)
66}
67
68func exifLine(it *library.Item) string {
69	m := it.Meta
70	var parts []string
71	for _, s := range []string{m.Camera, m.Lens, m.Aperture, m.Shutter} {
72		if s != "" {
73			parts = append(parts, s)
74		}
75	}
76	if m.ISO > 0 {
77		parts = append(parts, "ISO "+strconv.Itoa(m.ISO))
78	}
79	if !m.Taken.IsZero() {
80		parts = append(parts, m.Taken.Format("2006-01-02"))
81	}
82	return strings.Join(parts, " · ")
83}