diff options
Diffstat (limited to 'templates/page.templ')
-rw-r--r-- | templates/page.templ | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/templates/page.templ b/templates/page.templ new file mode 100644 index 0000000..08c17a0 --- /dev/null +++ b/templates/page.templ @@ -0,0 +1,115 @@ +package templates + +import ( + "os" + "net/url" + + "website/internal/config" +) + +var ( + css string +) + +func init() { + bytes, err := os.ReadFile("templates/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(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(path string, title string) string { + u, err := url.Parse("https://alanpearce-eu.goatcounter.com/count") + if err != nil { + panic(err) + } + q := u.Query() + q.Add("p", path) + q.Add("t", title) + u.RawQuery = q.Encode() + + return u.String() +} + +templ counter(path string, title string) { + <script data-goatcounter="https://alanpearce-eu.goatcounter.com/count" async src="https://gc.zgo.at/count.v4.js" crossorigin="anonymous" integrity="sha384-nRw6qfbWyJha9LhsOtSb2YJDyZdKvvCFh0fJYlkquSFjUxp9FVNugbfy8q1jdxI+"></script> + <noscript> + <img src={ string(templ.URL(mkURL(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 + }) +} |