Files
s/helios/build/generate-index.go

164 lines
3.6 KiB
Go
Raw Normal View History

2025-10-08 15:02:13 -07:00
package main
import (
2025-10-08 15:23:12 -07:00
"encoding/json"
2025-10-08 15:19:18 -07:00
"flag"
2025-10-08 15:02:13 -07:00
"fmt"
"html/template"
2025-10-08 15:23:12 -07:00
"log"
2025-10-08 15:02:13 -07:00
"os"
"path/filepath"
"sort"
2025-10-08 15:19:18 -07:00
"strings"
2025-10-08 15:02:13 -07:00
)
type IndexData struct {
2025-10-08 15:19:18 -07:00
Dir string
Files []FileEntry
RootURL string
2025-10-08 15:02:13 -07:00
}
2025-10-08 15:19:18 -07:00
type FileEntry struct {
2025-10-08 22:29:22 -07:00
Name string `json:"name"`
URL string `json:"url"`
Date string `json:"date,omitempty"`
Source string `json:"source,omitempty"`
Topic string `json:"topic,omitempty"`
Gradeband *string `json:"gradeband,omitempty"`
}
func parseFilename(name string) (date, source, topic string, gradeband *string) {
// Remove extension
nameWithoutExt := strings.TrimSuffix(name, filepath.Ext(name))
// Split by " - "
parts := strings.Split(nameWithoutExt, " - ")
if len(parts) < 2 {
// Can't parse, return empty
return
}
date = parts[0]
source = parts[1]
if len(parts) == 2 {
// No topic or gradeband
return
}
if len(parts) == 3 {
// Just topic, no gradeband
topic = parts[2]
return
}
// 4+ parts: third part is gradeband, remaining parts are topic
gb := parts[2]
gradeband = &gb
topic = strings.Join(parts[3:], " - ")
return
2025-10-08 15:19:18 -07:00
}
func generateIndex(dir string, rootURL string) error {
2025-10-08 15:02:13 -07:00
entries, err := os.ReadDir(dir)
if err != nil {
return fmt.Errorf("failed to read directory: %w", err)
}
2025-10-08 15:19:18 -07:00
// Normalize root URL (remove trailing slash)
rootURL = strings.TrimSuffix(rootURL, "/")
var fileNames []string
2025-10-08 15:02:13 -07:00
for _, entry := range entries {
name := entry.Name()
2025-10-08 22:29:22 -07:00
ext := filepath.Ext(name)
2025-10-08 22:35:31 -07:00
// Skip the index files, build files, directories, and hidden files
if !entry.IsDir() &&
name != "index.html" && name != "index.json" &&
2025-10-08 22:29:22 -07:00
ext != ".go" && ext != ".tmpl" &&
!filepath.HasPrefix(name, ".") {
2025-10-08 15:19:18 -07:00
fileNames = append(fileNames, name)
2025-10-08 15:02:13 -07:00
}
}
2025-10-08 15:19:18 -07:00
sort.Strings(fileNames)
// Build file entries with absolute URLs
var files []FileEntry
dirName := filepath.Base(dir)
for _, name := range fileNames {
url := fmt.Sprintf("%s/%s/%s", rootURL, dirName, name)
2025-10-08 22:29:22 -07:00
date, source, topic, gradeband := parseFilename(name)
2025-10-08 15:19:18 -07:00
files = append(files, FileEntry{
2025-10-08 22:29:22 -07:00
Name: name,
URL: url,
Date: date,
Source: source,
Topic: topic,
Gradeband: gradeband,
2025-10-08 15:19:18 -07:00
})
}
2025-10-08 15:02:13 -07:00
2025-10-08 22:35:31 -07:00
templatePath := "helios/build/index.html.tmpl"
2025-10-08 15:02:13 -07:00
tmpl, err := template.ParseFiles(templatePath)
if err != nil {
return fmt.Errorf("failed to parse template: %w", err)
}
indexPath := filepath.Join(dir, "index.html")
f, err := os.Create(indexPath)
if err != nil {
return fmt.Errorf("failed to create index.html: %w", err)
}
defer f.Close()
data := IndexData{
2025-10-08 15:19:18 -07:00
Dir: dirName,
Files: files,
RootURL: rootURL,
2025-10-08 15:02:13 -07:00
}
if err := tmpl.Execute(f, data); err != nil {
return fmt.Errorf("failed to execute template: %w", err)
}
2025-10-08 15:23:12 -07:00
log.Println(indexPath)
// Generate index.json
jsonPath := filepath.Join(dir, "index.json")
jsonFile, err := os.Create(jsonPath)
if err != nil {
return fmt.Errorf("failed to create index.json: %w", err)
}
defer jsonFile.Close()
encoder := json.NewEncoder(jsonFile)
encoder.SetIndent("", " ")
encoder.SetEscapeHTML(false)
if err := encoder.Encode(files); err != nil {
return fmt.Errorf("failed to encode JSON: %w", err)
}
log.Println(jsonPath)
2025-10-08 15:02:13 -07:00
return nil
}
func main() {
2025-10-08 15:32:19 -07:00
rootURL := flag.String("root", "https://s.fc.run", "Root domain URL for absolute links")
2025-10-08 15:19:18 -07:00
flag.Parse()
dirs := flag.Args()
if len(dirs) == 0 {
fmt.Println("Usage: generate-index [-root <url>] <directory> [<directory>...]")
fmt.Println(" -root string")
2025-10-08 15:32:19 -07:00
fmt.Println(" Root domain URL for absolute links (default \"https://s.fc.run\")")
2025-10-08 15:02:13 -07:00
os.Exit(1)
}
2025-10-08 15:19:18 -07:00
for _, dir := range dirs {
if err := generateIndex(dir, *rootURL); err != nil {
2025-10-08 15:23:12 -07:00
log.Fatalf("Error processing %s: %v", dir, err)
2025-10-08 15:02:13 -07:00
}
}
}