package templates import ( "context" "go.alanpearce.eu/website/internal/config" "io" "io/fs" "net/url" ) var ( css string ) func Setup() { bytes, err := fs.ReadFile(Files, "style.css") if err != nil { panic(err) } css = string(bytes) } type PageSettings struct { Title string Path string TitleAttrs templ.Attributes BodyAttrs templ.Attributes } func extendClasses(cs string, attrs templ.Attributes) string { if extras, exists := attrs["class"]; exists { return templ.Classes(cs, extras).String() } else { return cs } } templ menuItem(item config.MenuItem) { <a href={ templ.SafeURL(item.URL.String()) } if item.URL.IsAbs() { target="_blank" } >{ item.Name }</a> } templ Page(site *config.Config, page PageSettings) { <!DOCTYPE html> <html lang={ site.DefaultLanguage }> <head> <meta charset="utf-8"/> <meta name="viewport" content="width=device-width, initial-scale=1.0"/> <title>{ page.Title }</title> <link rel="alternate" type="application/atom+xml" title={ site.Title } href="/atom.xml"/> @style(css) </head> <body { page.BodyAttrs... }> <a class="skip" href="#main">Skip to main content</a> <header> <h2> <a href="/" class={ extendClasses("title p-name", page.TitleAttrs) } { page.TitleAttrs... }>{ site.Title }</a> </h2> <nav> for _, item := range site.Menus["main"] { @menuItem(item) } </nav> </header> <main id="main"> { children... } </main> <footer> Content is <a rel="license" href="http://creativecommons.org/licenses/by/4.0/">CC BY 4.0</a>. <a href="https://git.alanpearce.eu/website/">Site source code</a> is <a href="https://opensource.org/licenses/MIT">MIT</a> </footer> @counter(site, page.Path, page.Title) if site.InjectLiveReload { <script defer> new EventSource("/_/reload").onmessage = event => { console.log("got message", event) window.location.reload() }; </script> } </body> </html> } func mkURL(original config.URL, path string, title string) string { ou := *original.URL u := config.URL{ URL: &ou, } q := url.Values{} q.Add("p", path) q.Add("t", title) u.RawQuery = q.Encode() return u.String() } templ counter(config *config.Config, path string, title string) { <script data-goatcounter={ config.GoatCounter.String() } async src="https://stats.alanpearce.eu/count.v4.js" crossorigin="anonymous" integrity="sha384-nRw6qfbWyJha9LhsOtSb2YJDyZdKvvCFh0fJYlkquSFjUxp9FVNugbfy8q1jdxI+"></script> <noscript> <img src={ string(templ.URL(mkURL(config.GoatCounter, path, title))) }/> </noscript> } func style(css string) templ.Component { return templ.ComponentFunc(func(ctx context.Context, w io.Writer) (err error) { _, err = io.WriteString(w, "<style>\n"+css+"\n</style>") return }) }