1diff --git a/pkg/handler/router.go b/pkg/handler/router.go
2index bc81350d19a5296cae5d8da058bac29a69bff693..cb5d6f54dfbf444aa0830337c9f9044067d9c16b 100644
3--- a/pkg/handler/router.go
4+++ b/pkg/handler/router.go
5@@ -1,6 +1,7 @@
6 package handler
7
8 import (
9+ "fmt"
10 "net/http"
11
12 serverconfig "git.gabrielgio.me/cerrado/pkg/config"
13@@ -10,6 +11,7 @@ "git.gabrielgio.me/cerrado/pkg/handler/auth"
14 "git.gabrielgio.me/cerrado/pkg/handler/git"
15 "git.gabrielgio.me/cerrado/pkg/handler/static"
16 "git.gabrielgio.me/cerrado/pkg/service"
17+ "git.gabrielgio.me/cerrado/templates"
18 )
19
20 // Mount handler gets the requires service and repository to build the handlers
21@@ -53,7 +55,7 @@ mux.AddMiddleware(ext.DisableAuthentication)
22 }
23
24 mux.HandleFunc("/static/{file}", staticHandler)
25- mux.HandleFunc("/static/theme", cssStaticHandler)
26+ mux.HandleFunc(fmt.Sprintf("/static/theme%s.css", templates.Slug), cssStaticHandler) // add slug so css file can be cached forever.
27 mux.HandleFunc("/{name}/about/{$}", gitHandler.About)
28 mux.HandleFunc("/{name}", gitHandler.Multiplex)
29 mux.HandleFunc("/{name}/{rest...}", gitHandler.Multiplex)
30diff --git a/pkg/handler/static/handler.go b/pkg/handler/static/handler.go
31index 779c78660309a955ece24d643d21877b610c2cad..6cc884ea1370a2a0268e04ed70a75e4f978c7c9f 100644
32--- a/pkg/handler/static/handler.go
33+++ b/pkg/handler/static/handler.go
34@@ -1,6 +1,7 @@
35 package static
36
37 import (
38+ "bytes"
39 "fmt"
40 "io"
41 "io/fs"
42@@ -45,23 +46,32 @@ )
43
44 return func(w http.ResponseWriter, r *ext.Request) error {
45 ext.SetMIME(w, "text/css")
46+ w.Header().Add("Cache-Control", "max-age=31536000")
47+
48+ // use buffer so this function can fail before writing to http.ResponseWriter
49+ var buffer bytes.Buffer
50
51 var style *chroma.Style
52 style = darkStyle
53- w.Write([]byte("[data-bs-theme=\"dark\"] {\n"))
54- err := formatter.WriteCSS(&ws{w}, style)
55+ buffer.Write([]byte("[data-bs-theme=\"dark\"] {\n"))
56+ err := formatter.WriteCSS(&ws{&buffer}, style)
57 if err != nil {
58 return err
59 }
60- w.Write([]byte("}\n"))
61+ buffer.Write([]byte("}\n"))
62
63 style = lightStyle
64- w.Write([]byte("[data-bs-theme=\"light\"] {\n"))
65- err = formatter.WriteCSS(&ws{w}, style)
66+ buffer.Write([]byte("[data-bs-theme=\"light\"] {\n"))
67+ err = formatter.WriteCSS(&ws{&buffer}, style)
68 if err != nil {
69 return err
70 }
71- w.Write([]byte("\n}"))
72+ buffer.Write([]byte("}"))
73+
74+ _, err = io.Copy(w, &buffer)
75+ if err != nil {
76+ return err
77+ }
78
79 return nil
80 }, nil
81diff --git a/templates/base.qtpl b/templates/base.qtpl
82index e43fb67fa5b7c74e9a0caa9057788cf46a4a614e..1dddb57bb0f0f60829259fc2eb60561c823a5b6f 100644
83--- a/templates/base.qtpl
84+++ b/templates/base.qtpl
85@@ -60,8 +60,7 @@ <meta charset="utf-8">
86 <link rel="icon" href="data:,">
87 <title>{%= p.Title(ctx) %}</title>
88 <link rel="stylesheet" href="/static/main{%s Slug %}.css">
89- <link rel="stylesheet" href="/static/themes/dark">
90- <link rel="stylesheet" href="/static/themes/light">
91+ <link rel="stylesheet" href="/static/theme{%s Slug %}.css">
92 <html data-bs-theme="dark">
93 <meta content="text/html;charset=utf-8" http-equiv="Content-Type">
94 <meta name="viewport" content="width=device-width, initial-scale=1" />
95diff --git a/templates/base.qtpl.go b/templates/base.qtpl.go
96index 783de2c10402a1a33125b1f872bc3db488ede7ab..3c4d8a94cc1649c5efd739976e21c045f8582db4 100644
97--- a/templates/base.qtpl.go
98+++ b/templates/base.qtpl.go
99@@ -8,14 +8,16 @@ //line templates/base.qtpl:3
100 package templates
101
102 //line templates/base.qtpl:3
103-import (
104- "context"
105- "strconv"
106- "time" //line templates/base.qtpl:4
107+import "context"
108
109- //line templates/base.qtpl:5
110- //line templates/base.qtpl:7
111+//line templates/base.qtpl:4
112+import "strconv"
113
114+//line templates/base.qtpl:5
115+import "time"
116+
117+//line templates/base.qtpl:7
118+import (
119 qtio422016 "io"
120
121 qt422016 "github.com/valyala/quicktemplate"
122@@ -110,60 +112,64 @@ //line templates/base.qtpl:62
123 qw422016.E().S(Slug)
124 //line templates/base.qtpl:62
125 qw422016.N().S(`.css">
126- <link rel="stylesheet" href="/static/theme">
127+ <link rel="stylesheet" href="/static/theme`)
128+//line templates/base.qtpl:63
129+ qw422016.E().S(Slug)
130+//line templates/base.qtpl:63
131+ qw422016.N().S(`.css">
132 <html data-bs-theme="dark">
133 <meta content="text/html;charset=utf-8" http-equiv="Content-Type">
134 <meta name="viewport" content="width=device-width, initial-scale=1" />
135 </head>
136 <body>
137 `)
138-//line templates/base.qtpl:70
139+//line templates/base.qtpl:69
140 p.StreamNavbar(qw422016, ctx)
141-//line templates/base.qtpl:70
142+//line templates/base.qtpl:69
143 qw422016.N().S(`
144 <div class="container">
145 `)
146-//line templates/base.qtpl:72
147+//line templates/base.qtpl:71
148 p.StreamContent(qw422016, ctx)
149-//line templates/base.qtpl:72
150+//line templates/base.qtpl:71
151 qw422016.N().S(`
152 </div>
153 </body>
154 `)
155-//line templates/base.qtpl:75
156+//line templates/base.qtpl:74
157 p.StreamScript(qw422016, ctx)
158-//line templates/base.qtpl:75
159+//line templates/base.qtpl:74
160 qw422016.N().S(`
161 <script>
162 function a(){const e=window.matchMedia("(prefers-color-scheme: dark)").matches;document.documentElement.setAttribute("data-bs-theme",e?"dark":"light")}a(),window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change",a);
163 </script>
164 </html>
165 `)
166-//line templates/base.qtpl:80
167+//line templates/base.qtpl:79
168 }
169
170-//line templates/base.qtpl:80
171+//line templates/base.qtpl:79
172 func WritePageTemplate(qq422016 qtio422016.Writer, p Page, ctx context.Context) {
173-//line templates/base.qtpl:80
174+//line templates/base.qtpl:79
175 qw422016 := qt422016.AcquireWriter(qq422016)
176-//line templates/base.qtpl:80
177+//line templates/base.qtpl:79
178 StreamPageTemplate(qw422016, p, ctx)
179-//line templates/base.qtpl:80
180+//line templates/base.qtpl:79
181 qt422016.ReleaseWriter(qw422016)
182-//line templates/base.qtpl:80
183+//line templates/base.qtpl:79
184 }
185
186-//line templates/base.qtpl:80
187+//line templates/base.qtpl:79
188 func PageTemplate(p Page, ctx context.Context) string {
189-//line templates/base.qtpl:80
190+//line templates/base.qtpl:79
191 qb422016 := qt422016.AcquireByteBuffer()
192-//line templates/base.qtpl:80
193+//line templates/base.qtpl:79
194 WritePageTemplate(qb422016, p, ctx)
195-//line templates/base.qtpl:80
196+//line templates/base.qtpl:79
197 qs422016 := string(qb422016.B)
198-//line templates/base.qtpl:80
199+//line templates/base.qtpl:79
200 qt422016.ReleaseByteBuffer(qb422016)
201-//line templates/base.qtpl:80
202+//line templates/base.qtpl:79
203 return qs422016
204-//line templates/base.qtpl:80
205+//line templates/base.qtpl:79
206 }