1package pages
2
3import (
4 "fmt"
5 "html"
6 "html/template"
7 "reflect"
8 "strings"
9
10 "github.com/dustin/go-humanize"
11)
12
13func funcMap() template.FuncMap {
14 return template.FuncMap{
15 "split": func(s string) []string {
16 return strings.Split(s, "\n")
17 },
18 "truncateAt30": func(s string) string {
19 if len(s) <= 30 {
20 return s
21 }
22 return s[:30] + "…"
23 },
24 "splitOn": func(s, sep string) []string {
25 return strings.Split(s, sep)
26 },
27 "add": func(a, b int) int {
28 return a + b
29 },
30 "sub": func(a, b int) int {
31 return a - b
32 },
33 "cond": func(cond interface{}, a, b string) string {
34 if cond == nil {
35 return b
36 }
37
38 if boolean, ok := cond.(bool); boolean && ok {
39 return a
40 }
41
42 return b
43 },
44 "didOrHandle": func(did, handle string) string {
45 if handle != "" {
46 return fmt.Sprintf("@%s", handle)
47 } else {
48 return did
49 }
50 },
51 "assoc": func(values ...string) ([][]string, error) {
52 if len(values)%2 != 0 {
53 return nil, fmt.Errorf("invalid assoc call, must have an even number of arguments")
54 }
55 pairs := make([][]string, 0)
56 for i := 0; i < len(values); i += 2 {
57 pairs = append(pairs, []string{values[i], values[i+1]})
58 }
59 return pairs, nil
60 },
61 "append": func(s []string, values ...string) []string {
62 s = append(s, values...)
63 return s
64 },
65 "timeFmt": humanize.Time,
66 "byteFmt": humanize.Bytes,
67 "length": func(slice any) int {
68 v := reflect.ValueOf(slice)
69 if v.Kind() == reflect.Slice || v.Kind() == reflect.Array {
70 return v.Len()
71 }
72 return 0
73 },
74 "splitN": func(s, sep string, n int) []string {
75 return strings.SplitN(s, sep, n)
76 },
77 "escapeHtml": func(s string) template.HTML {
78 if s == "" {
79 return template.HTML("<br>")
80 }
81 return template.HTML(s)
82 },
83 "unescapeHtml": func(s string) string {
84 return html.UnescapeString(s)
85 },
86 "nl2br": func(text string) template.HTML {
87 return template.HTML(strings.Replace(template.HTMLEscapeString(text), "\n", "<br>", -1))
88 },
89 "unwrapText": func(text string) string {
90 paragraphs := strings.Split(text, "\n\n")
91
92 for i, p := range paragraphs {
93 lines := strings.Split(p, "\n")
94 paragraphs[i] = strings.Join(lines, " ")
95 }
96
97 return strings.Join(paragraphs, "\n\n")
98 },
99 "sequence": func(n int) []struct{} {
100 return make([]struct{}, n)
101 },
102 "subslice": func(slice any, start, end int) any {
103 v := reflect.ValueOf(slice)
104 if v.Kind() != reflect.Slice && v.Kind() != reflect.Array {
105 return nil
106 }
107 if start < 0 || start > v.Len() || end > v.Len() || start > end {
108 return nil
109 }
110 return v.Slice(start, end).Interface()
111 },
112 "markdown": func(text string) template.HTML {
113 return template.HTML(renderMarkdown(text))
114 },
115 "isNil": func(t any) bool {
116 // returns false for other "zero" values
117 return t == nil
118 },
119 "list": func(args ...any) []any {
120 return args
121 },
122 }
123}