Hi… I am well aware that this diff view is very suboptimal. It will be fixed when the refactored server comes along!
Fix group path trailing slash
// SPDX-License-Identifier: AGPL-3.0-only
// SPDX-FileContributor: Runxi Yu <https://runxiyu.org>
package main
import (
"net/url"
"path"
"strings"
)
func firstLine(s string) string {
before, _, _ := strings.Cut(s, "\n")
return before
}
func baseName(s string) string {
return path.Base(s)
}
func pathEscape(s string) string {
return url.PathEscape(s)
}
func queryEscape(s string) string {
return url.QueryEscape(s)
}
func dereference[T any](p *T) T {
return *p
}
func dereferenceOrZero[T any](p *T) T {
if p != nil {
return *p
}
var z T
return z
}
func minus(a, b int) int {
return a - b
}
// SPDX-License-Identifier: AGPL-3.0-only
// SPDX-FileContributor: Runxi Yu <https://runxiyu.org>
package main
import (
"embed"
"html/template"
"io/fs"
"net/http"
"github.com/tdewolff/minify/v2"
"github.com/tdewolff/minify/v2/html"
)
// We embed all source for easy AGPL compliance.
//
//go:embed .gitignore .gitattributes
//go:embed LICENSE README.md
//go:embed *.go go.mod go.sum
//go:embed *.scfg
//go:embed Makefile
//go:embed static/* templates/* scripts/* sql/*
//go:embed hookc/*.c
//go:embed vendor/*
var sourceFS embed.FS
var sourceHandler = http.StripPrefix(
"/:/source/",
http.FileServer(http.FS(sourceFS)),
)
//go:embed templates/* static/* hookc/hookc
var resourcesFS embed.FS
var templates *template.Template
func loadTemplates() (err error) {
minifier := minify.New()
minifierOptions := html.Minifier{
TemplateDelims: [2]string{"{{", "}}"},
KeepDefaultAttrVals: true,
} //exhaustruct:ignore
minifier.Add("text/html", &minifierOptions)
templates = template.New("templates").Funcs(template.FuncMap{
"first_line": firstLine,
"base_name": baseName,
"path_escape": pathEscape,
"query_escape": queryEscape,
"dereference_error": dereferenceOrZero[error],
"minus": minus,
})
err = fs.WalkDir(resourcesFS, "templates", func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
if !d.IsDir() {
content, err := fs.ReadFile(resourcesFS, path)
if err != nil {
return err
}
minified, err := minifier.Bytes("text/html", content)
if err != nil {
return err
}
_, err = templates.Parse(string(minified))
if err != nil {
return err
}
}
return nil
})
return err
}
var staticHandler http.Handler
func init() {
staticFS, err := fs.Sub(resourcesFS, "static")
if err != nil {
panic(err)
}
staticHandler = http.StripPrefix("/:/static/", http.FileServer(http.FS(staticFS)))
}
{{/*
SPDX-License-Identifier: AGPL-3.0-only
SPDX-FileContributor: Runxi Yu <https://runxiyu.org>
*/}}
{{- define "group_path_plain" -}}
{{- $p := . -}}
{{- range $i, $s := . -}}{{- $s -}}{{- if ne $i (len $p) -}}/{{- end -}}{{- end -}}
{{- range $i, $s := . -}}{{- $s -}}{{- if ne $i (minus (len $p) 1) -}}/{{- end -}}{{- end -}}
{{- end -}}
{{/*
SPDX-License-Identifier: AGPL-3.0-only
SPDX-FileContributor: Runxi Yu <https://runxiyu.org>
*/}}
{{- define "group" -}}
{{- $group_path := .group_path -}}
<!DOCTYPE html>
<html lang="en">
<head>
{{- template "head_common" . -}}
<title>{{- range $i, $s := .group_path -}}{{- $s -}}{{- if ne $i (len $group_path) -}}/{{- end -}}{{- end }} – {{ .global.forge_title -}}</title>
</head>
<body class="group">
{{- template "header" . -}}
<div class="padding-wrapper">
<p>{{- range $i, $s := .group_path -}}{{- $s -}}{{- if ne $i (len $group_path) }} / {{ end -}}{{- end -}}
<p>{{- range $i, $s := .group_path -}}{{- $s -}}{{- if ne $i (minus (len $group_path) 1) }} / {{ end -}}{{- end -}}
{{- if .description -}}
<p>{{- .description -}}</p>
{{- end -}}
{{- template "group_view" . -}}
</div>
{{- if .direct_access -}}
<div class="padding-wrapper">
<form method="POST" enctype="application/x-www-form-urlencoded">
<table class="rounded-footed">
<thead>
<tr>
<th class="title-row" colspan="2">
Create repo
</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Name</th>
<td class="tdinput">
<input id="repo-name-input" name="repo_name" type="text" />
</td>
</tr>
<tr>
<th scope="row">Description</th>
<td class="tdinput">
<input id="repo-desc-input" name="repo_desc" type="text" />
</td>
</tr>
<tr>
<th scope="row">Contrib</th>
<td class="tdinput">
<select id="repo-contrib-input" name="repo_contrib">
<option value="public">Public</option>
<option value="ssh_pubkey">SSH public key</option>
<option value="federated">Federated service</option>
<option value="registered_user">Registered user</option>
<option value="closed">Closed</option>
</select>
</td>
</tr>
</tbody>
<tfoot>
<tr>
<td class="th-like" colspan="2">
<div class="flex-justify">
<div class="left">
</div>
<div class="right">
<input class="btn-primary" type="submit" value="Create" />
</div>
</div>
</td>
</tr>
</tfoot>
</table>
</form>
</div>
{{- end -}}
<footer>
{{- template "footer" . -}}
</footer>
</body>
</html>
{{- end -}}