package main import ( "fmt" "log" "net/url" "os" "path/filepath" "go.alanpearce.eu/gomponents" "gopkg.in/yaml.v3" ) type URL struct { *url.URL } func (u *URL) UnmarshalYAML(value *yaml.Node) (err error) { var s string if err := value.Decode(&s); err != nil { return err } u.URL, err = url.Parse(s) return err } type Config struct { Title string Domain URL Forge URL Menu []*MenuLink Packages []string } type MenuLink struct { Name string URL URL } func must[T any](t T, err error) T { if err != nil { panic(err) } return t } func fatal(err error) { if err != nil { log.Fatal(err) } } func importString(config *Config, pkg string) string { return fmt.Sprintf("%s git %s", config.Domain.JoinPath(pkg), config.Forge.JoinPath(pkg), ) } func sourceString(config *Config, pkg string) string { return fmt.Sprintf("%s _ %s %s", config.Domain.JoinPath(pkg), config.Forge.JoinPath(pkg).String()+"/tree/main{/dir}", config.Forge.JoinPath(pkg).String()+"/tree/main{/dir}/{file}#n{line}", ) } func godocURL(config *Config, pkg string) string { return must(url.JoinPath("https://pkg.go.dev", packageImportPath(config, pkg))) } func badgeURL(config *Config, pkg string) string { return must(url.JoinPath("https://pkg.go.dev/badge/", packageImportPath(config, pkg))) } func packageImportPath(config *Config, pkg string) string { return config.Domain.JoinPath(pkg).String() } func packageForgeURL(config *Config, pkg string) string { return config.Forge.JoinPath(pkg).String() } func getConfig(filename string) (cfg *Config, err error) { cfg = new(Config) file, err := os.Open(filename) if err != nil { return nil, err } defer file.Close() dec := yaml.NewDecoder(file) dec.KnownFields(true) err = dec.Decode(cfg) if err != nil { return nil, err } return cfg, nil } const destDir = "dist" func renderToFile(c gomponents.Node, filename string) error { pathname := filepath.Join(destDir, filename) err := os.MkdirAll(filepath.Dir(pathname), 0755) if err != nil { return err } file, err := os.Create(pathname) if err != nil { return err } defer file.Close() return c.Render(file) } func main() { cfg, err := getConfig("vanity.yaml") fatal(err) err = renderToFile( ListPage(cfg), "index.html", ) fatal(err) for _, pkg := range cfg.Packages { err = renderToFile( PackagePage(cfg, pkg), filepath.Join(pkg, "index.html"), ) fatal(err) } }