about summary refs log tree commit diff stats
path: root/templates/page.templ
blob: 294b73e1903940b6a4e1dea0156bce5fe1e1201a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
	})
}