package main import ( "bytes" "log" "net/http" "os" chromahtml "github.com/alecthomas/chroma/v2/formatters/html" "github.com/alecthomas/chroma/v2/styles" "ridgwaysystems.org/paste/internal/handler" "ridgwaysystems.org/paste/internal/paste" ) func main() { port := getenv("PORT", "8081") dataDir := getenv("DATA_DIR", "data") // Generate syntax.css at startup (light + dark via media query) if err := generateSyntaxCSS("static/css/syntax.css"); err != nil { log.Printf("warning: could not generate syntax.css: %v", err) } store, err := paste.NewStore(dataDir) if err != nil { log.Fatal("paste store:", err) } h := handler.New(store) mux := http.NewServeMux() // Static files mux.Handle("GET /static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static")))) // Public routes mux.HandleFunc("GET /{$}", h.List) mux.HandleFunc("GET /{id}", h.ViewPaste) mux.HandleFunc("GET /raw/{id}", h.RawPaste) // Paste creation (auth required) mux.HandleFunc("GET /new", h.RequireAuth(h.NewPasteForm)) mux.HandleFunc("POST /new", h.RequireAuth(h.NewPastePost)) // Admin mux.HandleFunc("GET /admin", h.RequireAuth(h.AdminDashboard)) mux.HandleFunc("GET /admin/login", h.AdminLogin) mux.HandleFunc("POST /admin/login", h.AdminLoginPost) mux.HandleFunc("POST /admin/logout", h.RequireAuth(h.AdminLogout)) mux.HandleFunc("POST /admin/delete/{id}", h.RequireAuth(h.DeletePaste)) srv := handler.Chain(mux, handler.LoggingMiddleware, handler.SecurityHeadersMiddleware, ) log.Printf("paste.ridgwaysystems.org starting on :%s (DEV=%s)", port, os.Getenv("DEV")) log.Fatal(http.ListenAndServe(":"+port, srv)) } // generateSyntaxCSS writes a chroma CSS file with light and dark themes. func generateSyntaxCSS(path string) error { formatter := chromahtml.New(chromahtml.WithClasses(true)) var buf bytes.Buffer buf.WriteString("/* Auto-generated by chroma at server startup. Do not edit. */\n\n") if err := formatter.WriteCSS(&buf, styles.Get("github")); err != nil { return err } buf.WriteString("\n@media (prefers-color-scheme: dark) {\n") var dark bytes.Buffer if err := formatter.WriteCSS(&dark, styles.Get("github-dark")); err != nil { return err } buf.Write(dark.Bytes()) buf.WriteString("}\n") return os.WriteFile(path, buf.Bytes(), 0644) } func getenv(key, def string) string { if v := os.Getenv(key); v != "" { return v } return def }