diff options
Diffstat (limited to 'website.go')
| -rw-r--r-- | website.go | 285 |
1 files changed, 274 insertions, 11 deletions
@@ -1,12 +1,271 @@ package main import ( + "encoding/json" "fmt" "net/http" + "strings" + "sync" + + "github.com/a-h/templ" ) +func Assert(ok bool) { + if !ok { + panic("assertion failure") + } +} + +type Theme struct { + primary string + secondary string + accent string + extra string + text string + alt string + background string +} + +type FontPack struct { + Monospace string + Normal string +} + +type Style struct { + theme Theme + fontPack FontPack +} + +var ( + mu sync.RWMutex + themes = map[string]Theme{} + fontPacks = map[string]FontPack{} +) + +func SetFontPack(name string, fontPack FontPack) { + mu.Lock() + defer mu.Unlock() + fontPacks[name] = fontPack +} + +func GetFontPack(name string) (FontPack, bool) { + mu.RLock() + defer mu.RUnlock() + fontPack, ok := fontPacks[name] + return fontPack, ok +} + +func SetTheme(name string, theme Theme) { + mu.Lock() + defer mu.Unlock() + themes[name] = theme +} + +func GetTheme(name string) (Theme, bool) { + mu.RLock() + defer mu.RUnlock() + theme, ok := themes[name] + return theme, ok +} + +func currentStyle(r *http.Request) Style { + theme, ok := GetTheme("default") + Assert(ok) + fontPack, ok := GetFontPack("default") + Assert(ok) + style := Style{ + theme: theme, + fontPack: fontPack, + } + + if cookie, err := r.Cookie("theme"); err == nil { + if theme, ok := GetTheme(cookie.Value); ok { + style.theme = theme + } + } + + if cookie, err := r.Cookie("font-pack"); err == nil { + if fontPack, ok := GetFontPack(cookie.Value); ok { + style.fontPack = fontPack + } + } + + return style +} + +func (theme Theme) Vars() map[string]string { + return map[string]string{ + "primary": theme.primary, + "secondary": theme.secondary, + "accent": theme.accent, + "extra": theme.extra, + "text": theme.text, + "alt": theme.alt, + "background": theme.background, + } +} + +func (fontPack FontPack) Vars() map[string]string { + return map[string]string{ + "font-mono": fontPack.Monospace, + "font-normal": fontPack.Normal, + } +} + +func (style Style) Vars() map[string]string { + vars := style.theme.Vars() + for k, v := range style.fontPack.Vars() { + vars[k] = v + } + return vars +} + +func styleToCss(style Style) templ.SafeCSS { + var b strings.Builder + for k, v := range style.Vars() { + fmt.Fprintf(&b, "--%s:%s;", k, v) + } + return templ.SafeCSS(b.String()) +} + +type Project struct { + Name string + Type string + Desc []string + Cmd string + Link string +} + +var projects = []Project{ + { + Name: "CPU vs AI", + Type: "Game (made with Zig)", + Desc: []string{ + "A tower defense game where an AI chip on your motherboard", + "generates bugs! Place CPUs to destroy the bugs!", + "Don't let them corrupt your RAM!", + }, + }, + { + Name: "Eko", + Type: "Social Media Platform", + Desc: []string{ + "A terminal-native alternative", + "to Discord for Terminal", + "nerds!", + }, + }, + { + Name: "Trident", + Type: "IntelliJ Plugin", + Desc: []string{ + "A blazingly fast way to", + "Navigate to your mosta used", + "files. Minimize keystrokes", + "and maximize productivity!", + }, + }, + { + Name: "Dotfiles", + Type: "Configuration", + Desc: []string{ + "My Linux configuration,", + "includes Neovim, tmux and", + "other programs.", + }, + }, +} + +func styleHandler(cookie string, lookup func(string) (map[string]string, bool)) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + name := r.PathValue("name") + vars, ok := lookup(name) + if !ok { + http.NotFound(w, r) + return + } + http.SetCookie(w, &http.Cookie{ + Name: cookie, Value: name, Path: "/", + MaxAge: 31536000, SameSite: http.SameSiteLaxMode, + }) + w.Header().Set("Cache-Control", "no-store") + json.NewEncoder(w).Encode(vars) + } +} + func main() { - fmt.Println("foo") + carbonightCat := Theme{ + primary: "#94e2d5", + secondary: "#b4befe", + accent: "#74c7ec", + extra: "#a6e3a1", + text: "#cdd6f4", + alt: "#585b70", + background: "#1e1e2e", + } + darkness := Theme{ + primary: "#000000", + secondary: "#000000", + accent: "#000000", + extra: "#000000", + text: "#000000", + alt: "#000000", + background: "#000000", + } + dark := Theme{ + primary: "#54d7a9", + secondary: "#9b7eca", + accent: "#7ed4fb", + extra: "#8fcc75", + text: "#ffffff", + alt: "#999999", + background: "#000000", + } + light := Theme{ + primary: "#009399", + secondary: "#440b8e", + accent: "#177282", + extra: "#40a02b", + text: "#000000", + alt: "#4d4d4d", + background: "#ffffff", + } + banana := Theme{ + primary: "#ffdd44", + secondary: "#9b7eca", + accent: "#7ed4fb", + extra: "#000000", + text: "#ffffff", + alt: "#999999", + background: "#000000", + } + + jetbrains := FontPack{ + Monospace: "JetBrains Mono", + Normal: `system-ui, sans-serif`, + } + + minecraft := FontPack{ + Monospace: `"Monocraft", "JetBrains Mono", monospace`, + Normal: `"Monocraft", system-ui, sans-serif`, + } + + SetTheme("carbonight-cat", carbonightCat) + SetTheme("banana", banana) + SetTheme("black", dark) + SetTheme("dark", darkness) + + SetTheme("light", light) + SetTheme("white", light) + SetTheme("sun", light) + SetTheme("sunlight", light) + SetTheme("flashbang", light) + + SetTheme("default", carbonightCat) + + SetFontPack("jetbrains", jetbrains) + SetFontPack("minecraft", minecraft) + SetFontPack("default", jetbrains) mux := http.NewServeMux() @@ -14,22 +273,26 @@ func main() { mux.Handle("GET /public/", http.StripPrefix("/public/", fileServer)) mux.HandleFunc("GET /{$}", func(w http.ResponseWriter, r *http.Request) { - HomePage().Render(r.Context(), w) + HomePage(currentStyle(r)).Render(r.Context(), w) }) - mux.HandleFunc("GET /about", func(w http.ResponseWriter, r *http.Request) { - AboutPage().Render(r.Context(), w) + mux.HandleFunc("GET /skills", func(w http.ResponseWriter, r *http.Request) { + SkillsPage(currentStyle(r)).Render(r.Context(), w) }) - mux.HandleFunc("GET /items", func(w http.ResponseWriter, r *http.Request) { - data := []Item{ - {Name: "Foo", Active: true}, - {Name: "Bar", Active: true}, - {Name: "Baz", Active: false}, - } - ItemsPage(data).Render(r.Context(), w) + mux.HandleFunc("GET /projects", func(w http.ResponseWriter, r *http.Request) { + ProjectsPage(currentStyle(r), projects).Render(r.Context(), w) }) + mux.HandleFunc("GET /theme/{name}", styleHandler("theme", func(n string) (map[string]string, bool) { + theme, ok := GetTheme(n) + return theme.Vars(), ok + })) + mux.HandleFunc("GET /font-pack/{name}", styleHandler("font-pack", func(n string) (map[string]string, bool) { + fontPack, ok := GetFontPack(n) + return fontPack.Vars(), ok + })) + fmt.Println("Server running at http://localhost:8080") if err := http.ListenAndServe(":8080", mux); err != nil { panic(err) |
