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
|
/**
* AltGit - altgit
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Paolo Lulli <kevwe.com>
* @copyright Paolo Lulli 2026
*/
package rendering
import (
"html/template"
"net/http"
"os"
"path/filepath"
"repobrowser/internal/config"
"repobrowser/internal/gitrepo"
"strings"
"github.com/gin-gonic/gin"
)
func RenderPage(c *gin.Context, data PageData) {
tmpl, err := template.ParseFiles("templates/index.html")
if err != nil {
c.String(http.StatusInternalServerError, err.Error())
return
}
c.Status(http.StatusOK)
c.Header("Content-Type", "text/html; charset=utf-8")
tmpl.Execute(c.Writer, data)
}
func ActiveBranch(c *gin.Context, def string) string {
if b := c.Query("branch"); b != "" {
return b
}
return def
}
func RepoPath(cfg config.RepositoryBrowserConfiguration, name string) string {
if name == "" || strings.Contains(name, "/") || strings.Contains(name, "..") {
return ""
}
p := filepath.Join(cfg.Root, name)
// Confirm it stays inside reposRoot
rel, err := filepath.Rel(cfg.Root, p)
if err != nil || strings.HasPrefix(rel, "..") {
return ""
}
return p
}
// ResolveRepo validates the :repo param and returns (repoName, repoPath).
// Aborts with 404 on bad input.
func ResolveRepo(cfg config.RepositoryBrowserConfiguration, name string) (string, string, bool) {
//name := c.Param("repo")
p := RepoPath(cfg, name)
if p == "" {
//c.String(http.StatusNotFound, "repository not found")
return "", "", false
}
if _, err := os.Stat(p); err != nil {
//c.String(http.StatusNotFound, "repository not found")
return "", "", false
}
return name, p, true
}
func BasePageData(c *gin.Context, repoName, rp, tab string, crumb template.HTML) PageData {
all, cur := gitrepo.ListBranches(rp)
branch := ActiveBranch(c, cur)
return PageData{
Repo: repoName,
Branch: branch,
Branches: gitrepo.BuildBranchLinks(all, branch, repoName, tab),
ActiveTab: tab,
Breadcrumb: crumb,
}
}
func FileIcon(name string) string {
ext := ""
if i := strings.LastIndex(name, "."); i >= 0 {
ext = name[i+1:]
}
switch ext {
case "go":
return "🔵"
case "js", "ts", "jsx", "tsx":
return "🟡"
case "py":
return "🟢"
case "md":
return "📝"
case "sh", "bash":
return "⚙️"
case "json", "yaml", "yml", "toml":
return "🔧"
case "html", "css":
return "🌐"
case "rs":
return "🦀"
case "c", "cpp", "h":
return "🔩"
}
return "📄"
}
|