refactor: extract template funcs into separate file
This commit is contained in:
152
templates/funcs.go
Normal file
152
templates/funcs.go
Normal file
@@ -0,0 +1,152 @@
|
||||
package templates
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func dict(values ...any) (map[string]any, error) {
|
||||
if len(values)%2 != 0 {
|
||||
return nil, fmt.Errorf("dict expects even number of values, got %d", len(values))
|
||||
}
|
||||
out := make(map[string]any, len(values)/2)
|
||||
for i := 0; i < len(values); i += 2 {
|
||||
key, ok := values[i].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("dict key at index %d is not a string", i)
|
||||
}
|
||||
out[key] = values[i+1]
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func jsonAttr(v any) (template.HTMLAttr, error) {
|
||||
b, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("json marshal: %w", err)
|
||||
}
|
||||
return template.HTMLAttr(b), nil
|
||||
}
|
||||
|
||||
func genresParams(genres []int) string {
|
||||
if len(genres) == 0 {
|
||||
return ""
|
||||
}
|
||||
var b strings.Builder
|
||||
for i, g := range genres {
|
||||
if i > 0 {
|
||||
b.WriteByte('&')
|
||||
}
|
||||
b.WriteString("genres=")
|
||||
b.WriteString(strconv.Itoa(g))
|
||||
}
|
||||
return b.String()
|
||||
}
|
||||
|
||||
func hasGenre(id int, genres []int) bool {
|
||||
return slices.Contains(genres, id)
|
||||
}
|
||||
|
||||
func div(a, b float64) float64 {
|
||||
if b == 0 {
|
||||
return 0
|
||||
}
|
||||
return a / b
|
||||
}
|
||||
|
||||
func ceilDiv(a, b int) int {
|
||||
if b == 0 {
|
||||
return 0
|
||||
}
|
||||
return (a + b - 1) / b
|
||||
}
|
||||
|
||||
func idiv(a, b int) int {
|
||||
if b == 0 {
|
||||
return 0
|
||||
}
|
||||
return a / b
|
||||
}
|
||||
|
||||
func atoi(v any) int {
|
||||
s, ok := v.(string)
|
||||
if !ok {
|
||||
return 0
|
||||
}
|
||||
n, err := strconv.Atoi(s)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func seq(v any) []int {
|
||||
count := 0
|
||||
switch n := v.(type) {
|
||||
case int:
|
||||
count = n
|
||||
case int64:
|
||||
if n > int64(^uint(0)>>1) {
|
||||
count = 0
|
||||
} else {
|
||||
count = int(n)
|
||||
}
|
||||
}
|
||||
if count <= 0 {
|
||||
return []int{}
|
||||
}
|
||||
res := make([]int, count)
|
||||
for i := 0; i < count; i++ {
|
||||
res[i] = i
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func toInt(v any) int {
|
||||
switch n := v.(type) {
|
||||
case int:
|
||||
return n
|
||||
case int64:
|
||||
if n > int64(^uint(0)>>1) {
|
||||
return 0
|
||||
}
|
||||
return int(n)
|
||||
case float64:
|
||||
if n > float64(int(^uint(0)>>1)) {
|
||||
return 0
|
||||
}
|
||||
return int(n)
|
||||
case string:
|
||||
i, err := strconv.Atoi(n)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return i
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
func percent(current, total float64) float64 {
|
||||
if total == 0 {
|
||||
return 0
|
||||
}
|
||||
return (current / total) * 100
|
||||
}
|
||||
|
||||
func formatDate(dateStr string) string {
|
||||
t, err := time.Parse(time.RFC3339, dateStr)
|
||||
if err != nil {
|
||||
t, err = time.Parse("2006-01-02T15:04:05+00:00", dateStr)
|
||||
if err != nil {
|
||||
return dateStr
|
||||
}
|
||||
}
|
||||
return t.Format("Jan 2, 2006")
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package templates
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"html/template"
|
||||
@@ -9,10 +8,7 @@ import (
|
||||
"io/fs"
|
||||
"net/http"
|
||||
"path"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gin-gonic/gin/render"
|
||||
@@ -144,144 +140,3 @@ func (r *Renderer) ExecuteFragment(w io.Writer, name string, block string, data
|
||||
}
|
||||
return tmpl.ExecuteTemplate(w, block, data)
|
||||
}
|
||||
|
||||
func dict(values ...any) (map[string]any, error) {
|
||||
if len(values)%2 != 0 {
|
||||
return nil, fmt.Errorf("dict expects even number of values, got %d", len(values))
|
||||
}
|
||||
out := make(map[string]any, len(values)/2)
|
||||
for i := 0; i < len(values); i += 2 {
|
||||
key, ok := values[i].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("dict key at index %d is not a string", i)
|
||||
}
|
||||
out[key] = values[i+1]
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func jsonAttr(v any) (template.HTMLAttr, error) {
|
||||
b, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("json marshal: %w", err)
|
||||
}
|
||||
return template.HTMLAttr(b), nil
|
||||
}
|
||||
|
||||
func genresParams(genres []int) string {
|
||||
if len(genres) == 0 {
|
||||
return ""
|
||||
}
|
||||
var b strings.Builder
|
||||
for i, g := range genres {
|
||||
if i > 0 {
|
||||
b.WriteByte('&')
|
||||
}
|
||||
b.WriteString("genres=")
|
||||
b.WriteString(strconv.Itoa(g))
|
||||
}
|
||||
return b.String()
|
||||
}
|
||||
|
||||
func hasGenre(id int, genres []int) bool {
|
||||
return slices.Contains(genres, id)
|
||||
}
|
||||
|
||||
func div(a, b float64) float64 {
|
||||
if b == 0 {
|
||||
return 0
|
||||
}
|
||||
return a / b
|
||||
}
|
||||
|
||||
func ceilDiv(a, b int) int {
|
||||
if b == 0 {
|
||||
return 0
|
||||
}
|
||||
return (a + b - 1) / b
|
||||
}
|
||||
|
||||
func idiv(a, b int) int {
|
||||
if b == 0 {
|
||||
return 0
|
||||
}
|
||||
return a / b
|
||||
}
|
||||
|
||||
func atoi(v any) int {
|
||||
s, ok := v.(string)
|
||||
if !ok {
|
||||
return 0
|
||||
}
|
||||
n, err := strconv.Atoi(s)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func seq(v any) []int {
|
||||
count := 0
|
||||
switch n := v.(type) {
|
||||
case int:
|
||||
count = n
|
||||
case int64:
|
||||
if n > int64(^uint(0)>>1) {
|
||||
count = 0
|
||||
} else {
|
||||
count = int(n)
|
||||
}
|
||||
}
|
||||
if count <= 0 {
|
||||
return []int{}
|
||||
}
|
||||
res := make([]int, count)
|
||||
for i := 0; i < count; i++ {
|
||||
res[i] = i
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func toInt(v any) int {
|
||||
switch n := v.(type) {
|
||||
case int:
|
||||
return n
|
||||
case int64:
|
||||
if n > int64(^uint(0)>>1) {
|
||||
return 0
|
||||
}
|
||||
return int(n)
|
||||
case float64:
|
||||
if n > float64(int(^uint(0)>>1)) {
|
||||
return 0
|
||||
}
|
||||
return int(n)
|
||||
case string:
|
||||
i, err := strconv.Atoi(n)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return i
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
func percent(current, total float64) float64 {
|
||||
if total == 0 {
|
||||
return 0
|
||||
}
|
||||
return (current / total) * 100
|
||||
}
|
||||
|
||||
func formatDate(dateStr string) string {
|
||||
t, err := time.Parse(time.RFC3339, dateStr)
|
||||
if err != nil {
|
||||
t, err = time.Parse("2006-01-02T15:04:05+00:00", dateStr)
|
||||
if err != nil {
|
||||
return dateStr
|
||||
}
|
||||
}
|
||||
return t.Format("Jan 2, 2006")
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user