diff options
Diffstat (limited to 'templates/page.templ')
-rw-r--r-- | templates/page.templ | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/templates/page.templ b/templates/page.templ new file mode 100644 index 0000000..294b73e --- /dev/null +++ b/templates/page.templ @@ -0,0 +1,116 @@ +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 + }) +} |