main
Raw Download raw file
  1package index
  2
  3import (
  4	"embed"
  5	"fmt"
  6	"html/template"
  7	"os"
  8	"path/filepath"
  9
 10	"forge/internal/repo"
 11)
 12
 13//go:embed templates/root.html templates/category.html
 14var templateFS embed.FS
 15
 16var (
 17	rootTmpl     = template.Must(template.ParseFS(templateFS, "templates/root.html"))
 18	categoryTmpl = template.Must(template.ParseFS(templateFS, "templates/category.html"))
 19)
 20
 21type rootData struct {
 22	Categories []rootCategory
 23}
 24
 25type rootCategory struct {
 26	Name  string
 27	Repos []rootRepo
 28}
 29
 30type rootRepo struct {
 31	Name     string
 32	Category string
 33}
 34
 35type categoryData struct {
 36	Category string
 37	Repos    []repoEntry
 38}
 39
 40type repoEntry struct {
 41	Name string
 42}
 43
 44// GenerateAll creates index.html files for the root and each category
 45// directory under outputRoot.
 46func GenerateAll(outputRoot string, repos []repo.Repo) error {
 47	grouped := make(map[string][]repo.Repo)
 48	var categoryOrder []string
 49	seen := make(map[string]bool)
 50
 51	for _, r := range repos {
 52		if !seen[r.Category] {
 53			seen[r.Category] = true
 54			categoryOrder = append(categoryOrder, r.Category)
 55		}
 56		grouped[r.Category] = append(grouped[r.Category], r)
 57	}
 58
 59	// Generate root index.
 60	rd := rootData{}
 61	for _, cat := range categoryOrder {
 62		rc := rootCategory{Name: cat}
 63		for _, r := range grouped[cat] {
 64			rc.Repos = append(rc.Repos, rootRepo{Name: r.Name, Category: r.Category})
 65		}
 66		rd.Categories = append(rd.Categories, rc)
 67	}
 68
 69	err := writeTemplate(rootTmpl, filepath.Join(outputRoot, "index.html"), rd)
 70	if err != nil {
 71		return fmt.Errorf("generating root index: %w", err)
 72	}
 73
 74	// Generate per-category indexes.
 75	for _, cat := range categoryOrder {
 76		cd := categoryData{Category: cat}
 77		for _, r := range grouped[cat] {
 78			cd.Repos = append(cd.Repos, repoEntry{Name: r.Name})
 79		}
 80
 81		catDir := filepath.Join(outputRoot, cat)
 82		err := os.MkdirAll(catDir, 0o755)
 83		if err != nil {
 84			return fmt.Errorf("creating category dir (category=%s): %w", cat, err)
 85		}
 86
 87		err = writeTemplate(categoryTmpl, filepath.Join(catDir, "index.html"), cd)
 88		if err != nil {
 89			return fmt.Errorf("generating category index (category=%s): %w", cat, err)
 90		}
 91	}
 92
 93	return nil
 94}
 95
 96func writeTemplate(tmpl *template.Template, path string, data any) error {
 97	err := os.MkdirAll(filepath.Dir(path), 0o755)
 98	if err != nil {
 99		return fmt.Errorf("creating output dir (path=%s): %w", path, err)
100	}
101
102	f, err := os.Create(path)
103	if err != nil {
104		return fmt.Errorf("creating file (path=%s): %w", path, err)
105	}
106	defer f.Close()
107
108	err = tmpl.Execute(f, data)
109	if err != nil {
110		return fmt.Errorf("executing template (path=%s): %w", path, err)
111	}
112	return nil
113}