diff options
Diffstat (limited to 'templates')
-rw-r--r-- | templates/404.templ | 13 | ||||
-rw-r--r-- | templates/homepage.templ | 42 | ||||
-rw-r--r-- | templates/list.templ | 51 | ||||
-rw-r--r-- | templates/page.templ | 115 | ||||
-rw-r--r-- | templates/post.templ | 51 | ||||
-rw-r--r-- | templates/tags.templ | 23 |
6 files changed, 295 insertions, 0 deletions
diff --git a/templates/404.templ b/templates/404.templ new file mode 100644 index 0000000..4b5e52a --- /dev/null +++ b/templates/404.templ @@ -0,0 +1,13 @@ +package templates + +import "website/internal/config" + +templ NotFound(config config.Config, path string) { + @Page(config, PageSettings{ + Title: "Not Found", + Path: path, + }) { + <h1>404</h1> + <h2>ʕノ•ᴥ•ʔノ ︵ ┻━┻</h2> + } +} diff --git a/templates/homepage.templ b/templates/homepage.templ new file mode 100644 index 0000000..0afbb2f --- /dev/null +++ b/templates/homepage.templ @@ -0,0 +1,42 @@ +package templates + +import ( + "website/internal/config" + "website/internal/content" +) + +templ Homepage(config config.Config, posts []content.Post, content string) { + @Page(config, PageSettings{ + Title: config.Title, + TitleAttrs: templ.Attributes{ + "class": "p-name u-url", + }, + Path: "/", + BodyAttrs: templ.Attributes{ + "class": "h-card", + }, + }) { + <div id="content"> + @Unsafe(content) + </div> + <section> + <h2>Latest Posts</h2> + @list(posts[0:3]) + </section> + <section> + <h2>Elsewhere on the Internet</h2> + <ul class="elsewhere"> + <li> + <a class="u-email" rel="me" href={ templ.SafeURL("mailto:" + config.Email) }> + { config.Email } + </a> + </li> + for _, link := range config.Menus["me"] { + <li> + <a class="u-url" rel="me" href={ templ.SafeURL(link.URL.String()) }>{ link.Name }</a> + </li> + } + </ul> + </section> + } +} diff --git a/templates/list.templ b/templates/list.templ new file mode 100644 index 0000000..602c15c --- /dev/null +++ b/templates/list.templ @@ -0,0 +1,51 @@ +package templates + +import ( + "website/internal/config" + "website/internal/content" +) + +templ TagPage(config config.Config, tag string, posts []content.Post, path string) { + @Page(config, PageSettings{ + Title: tag, + Path: path, + TitleAttrs: templ.Attributes{ + "class": "p-author h-card", + "rel": "author", + }, + }) { + <div class="filter"> + <h3 class="filter">#{ tag }</h3> + <small> + <a href="../">Remove filter</a> + </small> + </div> + @list(posts) + } +} + +templ ListPage(config config.Config, posts []content.Post, path string) { + @Page(config, PageSettings{ + Title: config.Title, + TitleAttrs: templ.Attributes{ + "class": "p-author h-card", + "rel": "author", + }, + Path: path, + }) { + @list(posts) + } +} + +templ list(posts []content.Post) { + <ul class="h-feed"> + for _, post := range posts { + <li class="h-entry"> + <span> + @postDate(post.Date) + </span> + <a class="p-name u-url" href={ templ.SafeURL(post.URL) }>{ post.Title }</a> + </li> + } + </ul> +} 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 + }) +} diff --git a/templates/post.templ b/templates/post.templ new file mode 100644 index 0000000..5b09d4b --- /dev/null +++ b/templates/post.templ @@ -0,0 +1,51 @@ +package templates + +import ( + "time" + "website/internal/config" + "website/internal/content" +) + +func Unsafe(html string) templ.Component { + return templ.ComponentFunc(func(ctx context.Context, w io.Writer) (err error) { + _, err = io.WriteString(w, html) + return + }) +} + +templ postDate(d time.Time) { + <time class="dt-published" datetime={ d.UTC().Format(time.RFC3339) }> + { d.Format("2006-01-02") } + </time> +} + +templ PostPage(config config.Config, post content.Post) { + @Page(config, PageSettings{ + Title: post.Title, + TitleAttrs: templ.Attributes{ + "class": "p-author h-card", + "rel": "author", + }, + Path: post.URL, + }) { + <article class="h-entry"> + <h1 class="p-name">{ post.Title }</h1> + <p> + @postDate(post.Date) + </p> + <div class="e-content"> + @Unsafe(post.Content) + </div> + <div class="tags"> + Tags: + <ul class="p-categories tags"> + for _, tag := range post.Taxonomies.Tags { + <li> + @tagLink(tag, templ.Attributes{"class": "p-category"}) + </li> + } + </ul> + </div> + </article> + } +} diff --git a/templates/tags.templ b/templates/tags.templ new file mode 100644 index 0000000..7218ca1 --- /dev/null +++ b/templates/tags.templ @@ -0,0 +1,23 @@ +package templates + +import "website/internal/config" + +templ tagLink(tag string, attrs templ.Attributes) { + <a { attrs... } href={ templ.SafeURL("/tags/" + tag) }>#{ tag }</a> +} + +templ TagsPage(config config.Config, title string, tags []string, path string) { + @Page(config, PageSettings{ + Title: title, + Path: path, + }) { + <h3 class="filter">Tags</h3> + <ul class="tags"> + for _, tag := range tags { + <li class="h-feed"> + @tagLink(tag, templ.Attributes{}) + </li> + } + </ul> + } +} |