Commit e0c777c

HPCesia <me@hpcesia.com>
2026-07-01 19:00:19
Add multi-repo index page template and generation
1 parent d635a23
pkg/templates/index_multi.gohtml
@@ -0,0 +1,67 @@
+{{- /*gotype: github.com/antonmedv/gitmal/pkg/templates.MultiRepoIndexParams*/ -}}
+{{ define "head" }}
+<style>
+.repo-list {
+    max-width: 900px;
+    margin: 0 auto;
+    padding: 0;
+}
+.repo-list h1 {
+    font-size: 24px;
+    margin-bottom: 24px;
+    font-weight: 600;
+}
+.repo-card {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    padding: 16px 20px;
+    margin-bottom: 8px;
+    border-radius: 8px;
+    border: 1px solid var(--border);
+    transition: border-color 0.15s;
+}
+.repo-card:hover {
+    border-color: var(--link);
+}
+.repo-card a {
+    color: var(--link);
+    font-size: 16px;
+    font-weight: 600;
+    text-decoration: none;
+}
+.repo-card a:hover {
+    text-decoration: underline;
+}
+.repo-card .repo-desc {
+    font-size: 14px;
+    color: var(--fg2);
+    margin-top: 4px;
+}
+.repo-card .repo-time {
+    font-size: 13px;
+    color: var(--fg3);
+    white-space: nowrap;
+    flex-shrink: 0;
+    margin-left: 16px;
+}
+</style>
+{{ end }}
+{{ define "body" }}
+<div class="repo-list">
+    <h1>{{ .Title }}</h1>
+    {{ range .Repos }}
+    <div class="repo-card">
+        <div>
+            <a href="{{ .Href }}">{{ .Name }}</a>
+            {{ if ne .Description "" }}
+            <div class="repo-desc">{{ .Description }}</div>
+            {{ end }}
+        </div>
+        {{ if not .LastUpdated.IsZero }}
+        <div class="repo-time">{{ .LastUpdated.Format "2006-01-02 15:04" }}</div>
+        {{ end }}
+    </div>
+    {{ end }}
+</div>
+{{ end }}
pkg/templates/templates.go
@@ -62,6 +62,10 @@ var CommitsListTemplate = Must(Must(layout.Clone()).Parse(commitsListContent))
 var commitContent string
 var CommitTemplate = Must(Must(layout.Clone()).Parse(commitContent))
 
+//go:embed index_multi.gohtml
+var indexMultiContent string
+var MultiRepoIndexTemplate = Must(Must(layout.Clone()).Parse(indexMultiContent))
+
 //go:embed preview.gohtml
 var previewContent string
 var PreviewTemplate = Must(New("preview").Parse(previewContent))
@@ -216,3 +220,17 @@ type PreviewParams struct {
 	Count  int
 	Themes []PreviewCard
 }
+
+type RepoIndexEntry struct {
+	Name        string
+	Slug        string
+	Href        string
+	Description string
+	LastUpdated time.Time
+}
+
+type MultiRepoIndexParams struct {
+	LayoutParams
+	Title string
+	Repos []RepoIndexEntry
+}
index_multi.go
@@ -0,0 +1,77 @@
+package main
+
+import (
+	"fmt"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"strings"
+	"time"
+
+	"github.com/antonmedv/gitmal/pkg/templates"
+)
+
+func generateMultiRepoIndex(repos []RepoEntry, siteName string, params Params) error {
+	entries := make([]templates.RepoIndexEntry, 0, len(repos))
+
+	for _, repo := range repos {
+		lastTime := lastCommitTime(repo.Path, repo.DefaultBranch)
+		entries = append(entries, templates.RepoIndexEntry{
+			Name:        repo.Name,
+			Slug:        repo.Slug,
+			Href:        filepath.ToSlash(filepath.Join(repo.Slug, "index.html")),
+			Description: repo.Description,
+			LastUpdated: lastTime,
+		})
+	}
+
+	outDir := params.OutputDir
+	if err := os.MkdirAll(outDir, 0o755); err != nil {
+		return err
+	}
+
+	f, err := os.Create(filepath.Join(outDir, "index.html"))
+	if err != nil {
+		return err
+	}
+	defer f.Close()
+
+	err = templates.MultiRepoIndexTemplate.ExecuteTemplate(f, "layout.gohtml", templates.MultiRepoIndexParams{
+		LayoutParams: templates.LayoutParams{
+			Title:            siteName,
+			Name:             siteName,
+			SiteName:         siteName,
+			Dark:             params.Dark,
+			RootHref:         "./",
+			RepoHref:         "./",
+			Selected:         "",
+			InlineStyles:     params.InlineStyles,
+			IsMultiRepoIndex: true,
+		},
+		Title: siteName,
+		Repos: entries,
+	})
+	if err != nil {
+		return fmt.Errorf("render multi-repo index: %w", err)
+	}
+
+	return nil
+}
+
+func lastCommitTime(repoPath, defaultBranch string) time.Time {
+	cmd := exec.Command("git", "log", "-1", "--format=%ct", defaultBranch)
+	cmd.Dir = repoPath
+	out, err := cmd.Output()
+	if err != nil {
+		return time.Time{}
+	}
+	ts := strings.TrimSpace(string(out))
+	if ts == "" {
+		return time.Time{}
+	}
+	var unix int64
+	if _, err := fmt.Sscanf(ts, "%d", &unix); err != nil {
+		return time.Time{}
+	}
+	return time.Unix(unix, 0)
+}