package main import ( "encoding/json" "flag" "fmt" "html/template" "log" "os" "path/filepath" "sort" "strings" ) type IndexData struct { Dir string Files []FileEntry RootURL string } type FileEntry struct { Name string `json:"name"` URL string `json:"url"` } func generateIndex(dir string, rootURL string) error { entries, err := os.ReadDir(dir) if err != nil { return fmt.Errorf("failed to read directory: %w", err) } // Normalize root URL (remove trailing slash) rootURL = strings.TrimSuffix(rootURL, "/") var fileNames []string for _, entry := range entries { name := entry.Name() // Skip the index files themselves and hidden files if name != "index.html" && name != "index.json" && !filepath.HasPrefix(name, ".") { fileNames = append(fileNames, name) } } 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) files = append(files, FileEntry{ Name: name, URL: url, }) } templatePath := "build/index.html.tmpl" 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{ Dir: dirName, Files: files, RootURL: rootURL, } if err := tmpl.Execute(f, data); err != nil { return fmt.Errorf("failed to execute template: %w", err) } 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) return nil } func main() { rootURL := flag.String("root", "https://ss-6r6jq.ondigitalocean.app", "Root domain URL for absolute links") flag.Parse() dirs := flag.Args() if len(dirs) == 0 { fmt.Println("Usage: generate-index [-root ] [...]") fmt.Println(" -root string") fmt.Println(" Root domain URL for absolute links (default \"https://ss-6r6jq.ondigitalocean.app\")") os.Exit(1) } for _, dir := range dirs { if err := generateIndex(dir, *rootURL); err != nil { log.Fatalf("Error processing %s: %v", dir, err) } } }