piekarnikgosipl/main.go

197 lines
4.3 KiB
Go

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"))))
}