package main //go:generate go tool templ generate templates import ( "bytes" "context" "fmt" "io" "log" "net/http" "os" "path/filepath" "piekarnikgosi/data" "piekarnikgosi/html" "piekarnikgosi/utils" "sort" "strings" "sync" "github.com/tdewolff/minify/v2" mcss "github.com/tdewolff/minify/v2/css" mhtml "github.com/tdewolff/minify/v2/html" mjs "github.com/tdewolff/minify/v2/js" ) type ComponentRenderer interface { Render(ctx context.Context, w io.Writer) error } var minifier = sync.OnceValue(func() *minify.M { m := minify.New() m.Add("text/html", &mhtml.Minifier{ KeepDocumentTags: true, KeepEndTags: true, }) m.Add("text/css", &mcss.Minifier{}) m.Add("application/javascript", &mjs.Minifier{}) return m }) func minifyFile(path, mediatype string) { data, err := os.ReadFile(path) if err != nil { log.Fatal(err) } err = os.WriteFile(path, minifyData(mediatype, data), 0666) if err != nil { log.Fatal(err) } } func minifyData(mediatype string, data []byte) []byte { b, err := minifier().Bytes(mediatype, data) if err != nil { log.Fatal(err) } return b } func saveFile(name string, comp ComponentRenderer) { var buf bytes.Buffer err := comp.Render(context.Background(), &buf) if err != nil { log.Fatal(err) } minified := minifyData("text/html", buf.Bytes()) err = os.WriteFile("www/"+name+".html", minified, 0666) if err != nil { log.Fatal(err) } } func portfolioImages(page string) []string { entries, err := os.ReadDir("img/portfolio/" + page) if err != nil { log.Fatal(err) } var names []string for _, e := range entries { if filepath.Ext(e.Name()) == ".avif" { name := page + "/" + e.Name() names = append(names, name) } } sort.Strings(names) return names } func to_url(input string) string { lower_case := strings.ToLower(input) return "portfolio_" + strings.NewReplacer(" ", "_", "ł", "l", "ó", "o").Replace(lower_case) } func portfolioPages() { entries, err := os.ReadDir("img/portfolio") if err != nil { log.Fatal(err) } var pages []string for _, e := range entries { pages = append(pages, e.Name()) } sort.Strings(pages) for i, page := range pages { images := portfolioImages(page) if i == 0 { saveFile("portfolio", html.Portfolio(images, "portfolio", pages)) } else { saveFile(to_url(page), html.Portfolio(images, to_url(page), pages)) } } } func generateHTML() { log.Println("generating html") saveFile(`index`, html.Index()) saveFile(`kawiarnia`, html.Kawiarnia()) saveFile(`wyroby`, html.Wyroby(data.Cakes, "wyroby")) saveFile(`wyroby_deserki`, html.Wyroby(data.Desserts, "wyroby_deserki")) saveFile(`wyroby_torty`, html.WyrobyTorty()) saveFile(`wyroby_slodkie_stoly`, html.WyrobySlodkieStoly()) saveFile(`wyroby_lody`, html.WyrobyLody()) portfolioPages() } func mergeStyles() { log.Println("generating css") cssFiles := []string{ "normalize.css", "base.css", "components.css", "home.css", "layout.css", "wyroby.css", "wyroby_torty.css", "wyroby_slodkie_stoly.css", "wyroby_lody.css", "portfolio.css", "kawiarnia.css", } var bundledCSS []byte for _, fileName := range cssFiles { filePath := fmt.Sprint("css/", fileName) content, err := os.ReadFile(filePath) if err != nil { log.Fatal(err) } bundledCSS = append(bundledCSS, content...) bundledCSS = append(bundledCSS, '\n') } minified := minifyData("text/css", bundledCSS) err := os.WriteFile("www/style.css", minified, 0666) if err != nil { log.Fatal(err) } } func ensureDir() { log.Println("creating directories") os.MkdirAll("www/images", 0777) entries, _ := os.ReadDir("www") for _, e := range entries { if !e.IsDir() && filepath.Ext(e.Name()) == ".html" { os.Remove("www/" + e.Name()) } } } func mustCopy(src, dst string) { _, err := utils.CopyIfNotExists(src, dst) if err != nil { log.Fatalf("copying %s: %s", src, err) } } func main() { ensureDir() generateHTML() mergeStyles() mustCopy("img/favicon.avif", "www/images/favicon.avif") mustCopy("img/logo.svg", "www/images/logo.svg") mustCopy("js/portfolio.js", "www/portfolio.js") minifyFile("www/portfolio.js", "application/javascript") mustCopy("js/htmx.min.js", "www/htmx.min.js") if len(os.Args) > 1 { return } log.Println("listening on :8000") log.Fatal(http.ListenAndServe(":8000", http.FileServer(http.Dir("www")))) }