summaryrefslogtreecommitdiff
path: root/internal/generator/utils.go
blob: 01507b063daffdfe72ab71f8b7df658f7f311e0f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
package generator

import (
	"fmt"
	"os"
	"path/filepath"
	"strings"

	"mokhan.ca/xlgmokha/gitmal/internal/git"
	"mokhan.ca/xlgmokha/gitmal/internal/templates"
)

const Dot = "·"

func Echo(a ...any) {
	_, _ = fmt.Fprintln(os.Stderr, a...)
}

func breadcrumbs(rootName string, path string, isFile bool) []templates.Breadcrumb {
	// Root list
	if path == "" {
		return []templates.Breadcrumb{
			{
				Name:  rootName,
				Href:  "./index.html",
				IsDir: true,
			},
		}
	}

	// Paths from git are already with '/'
	parts := strings.Split(path, "/")

	// Build breadcrumbs relative to the file location so links work in static output
	// Example: for a/b/c.txt, at /blob/<ref>/a/b/c.txt.html
	// - root: ../../index.html
	// - a: ../index.html
	// - b: index.html
	// - c.txt: (no link)
	d := len(parts)

	// current directory depth relative to ref
	if isFile {
		d -= 1
	}

	crumbs := make([]templates.Breadcrumb, 0, len(parts))

	// root
	crumbs = append(crumbs, templates.Breadcrumb{
		Name:  rootName,
		Href:  "./" + strings.Repeat("../", d) + "index.html",
		IsDir: true,
	})

	// intermediate directories
	for i := 0; i < len(parts)-1; i++ {
		name := parts[i]
		// target directory depth t = i+1
		up := d - (i + 1)
		href := "./" + strings.Repeat("../", up) + "index.html"
		crumbs = append(crumbs, templates.Breadcrumb{
			Name:  name,
			Href:  href,
			IsDir: true,
		})
	}

	// final file (no link)
	crumbs = append(crumbs, templates.Breadcrumb{
		Name:  parts[len(parts)-1],
		IsDir: !isFile,
	})

	return crumbs
}

func humanizeSize(size int64) string {
	const unit = 1024
	if size < unit {
		return fmt.Sprintf("%d B", size)
	}
	div, exp := int64(unit), 0
	for n := size / unit; n >= unit; n /= unit {
		div *= unit
		exp++
	}
	return fmt.Sprintf("%.1f %cB", float64(size)/float64(div), "KMGTPE"[exp])
}

func isMarkdown(path string) bool {
	lower := strings.ToLower(path)
	if strings.HasSuffix(lower, ".md") || strings.HasSuffix(lower, ".markdown") || strings.HasSuffix(lower, ".mdown") || strings.HasSuffix(lower, ".mkd") || strings.HasSuffix(lower, ".mkdown") {
		return true
	}
	return false
}

func isImage(path string) bool {
	switch filepath.Ext(path) {
	case ".png", ".jpg", ".jpeg", ".gif", ".webp":
		return true
	default:
		return false
	}
}

func ContainsBranch(branches []git.Ref, branch string) bool {
	for _, b := range branches {
		if b.String() == branch {
			return true
		}
	}
	return false
}

func HasConflictingBranchNames(branches []git.Ref) (bool, git.Ref, git.Ref) {
	uniq := make(map[string]git.Ref, len(branches))
	for _, b := range branches {
		if a, exists := uniq[b.DirName()]; exists {
			return true, a, b
		}
		uniq[b.DirName()] = b
	}
	return false, git.Ref{}, git.Ref{}
}