// Package views renders the server-side HTML with gomponents. // Every function returns a g.Node. Handlers pass the result to Render. package views import ( "net/http" "hearthforge/internal/highlight" "hearthforge/internal/config" "hearthforge/internal/db" "hearthforge/internal/util" g "maragu.dev/gomponents" . "maragu.dev/gomponents/html" ) // Page carries the data the page shell needs. type Page struct { Title string User *db.SessionUser Cfg *config.Config } // Layout renders the full HTML document around the body nodes. func Layout(p Page, body ...g.Node) g.Node { pageTitle := "Hearthforge" if p.Title != "" { pageTitle = p.Title + " — Hearthforge" } owner := "" if p.Cfg != nil { owner = p.Cfg.OwnerDisplayName } return HTML(Lang("en"), Head( Meta(Charset("UTF-8")), Meta(Name("viewport"), Content("width=500")), TitleEl(g.Text(pageTitle)), Script(Src("/assets/theme.js")), Link(Rel("icon"), Type("image/svg+xml"), Href("/assets/favicon.svg")), Link(Rel("stylesheet"), Href("/assets/css/main.css")), Link(Rel("stylesheet"), Href("/assets/code-theme.css?v="+highlight.CSSVersion())), Script(Src("/assets/app.js"), Defer()), ), Body( Header(Class("site-header"), Nav(Class("site-nav"), A(Href("/"), Class("site-logo"), Img(Src("/assets/favicon.svg"), Class("logo-icon"), Alt(""), Aria("hidden", "true")), Span(Class("logo-text"), g.Text("Hearthforge")), ), Div(Class("nav-links"), g.Iff(p.User != nil, func() g.Node { return g.Group{ A(Href("/settings"), Class("nav-user"), Avatar(&p.User.ID, &p.User.AvatarVersion, 24), Span(g.Text(util.DisplayName(p.User.Username, owner))), ), Form(Method("POST"), Action("/logout"), Class("inline-form"), Button(Type("submit"), Class("btn btn-sm"), g.Text("Sign out")), ), } }), g.If(p.User == nil, g.Group{ A(Href("/login"), Class("btn btn-sm"), g.Text("Sign in")), A(Href("/register"), Class("btn btn-sm btn-primary"), g.Text("Register")), }), ), ), ), Main(Class("site-main"), g.Group(body)), Footer(Class("site-footer"), P(g.Text("Hearthforge — hosted by "+owner)), ), ), ) } // Render writes a full HTML document to the response. func Render(w http.ResponseWriter, status int, node g.Node) { w.Header().Set("Content-Type", "text/html; charset=utf-8") w.Header().Set("Cache-Control", "no-store") w.WriteHeader(status) _ = Doctype(node).Render(w) }