1diff --git a/templates/commit.qtpl b/templates/commit.qtpl
2new file mode 100644
3index 0000000000000000000000000000000000000000..307017214fafd55d950c5c810bc0e8ac60e7a74b
4--- /dev/null
5+++ b/templates/commit.qtpl
6@@ -0,0 +1,17 @@
7+{% import "github.com/go-git/go-git/v5/plumbing/object" %}
8+
9+{% func Commit(name string, c *object.Commit) %}
10+ <div class="row event">
11+ <div class="row">
12+ <div class="col-md">
13+ <a title="{%s c.Hash.String() %}" href="/{%s name %}/commit/{%s c.Hash.String() %}">{%s c.Hash.String()[0:8] %}</a>
14+ </div>
15+ <div class="col-md text-md-end">
16+ <a title="{%s c.Committer.Email %}" href="mailto:{%s c.Committer.Email %}">{%s c.Committer.Name %}</a>
17+ </div>
18+ </div>
19+ <div class="code-view">
20+ <pre>{%s c.Message %}</pre>
21+ </div>
22+ </div>
23+{% endfunc %}
24diff --git a/templates/commit.qtpl.go b/templates/commit.qtpl.go
25new file mode 100644
26index 0000000000000000000000000000000000000000..7f4649928a5d7a7c49f91dadb008170a30dc8d12
27--- /dev/null
28+++ b/templates/commit.qtpl.go
29@@ -0,0 +1,100 @@
30+// Code generated by qtc from "commit.qtpl". DO NOT EDIT.
31+// See https://github.com/valyala/quicktemplate for details.
32+
33+//line commit.qtpl:1
34+package templates
35+
36+//line commit.qtpl:1
37+import "github.com/go-git/go-git/v5/plumbing/object"
38+
39+//line commit.qtpl:3
40+import (
41+ qtio422016 "io"
42+
43+ qt422016 "github.com/valyala/quicktemplate"
44+)
45+
46+//line commit.qtpl:3
47+var (
48+ _ = qtio422016.Copy
49+ _ = qt422016.AcquireByteBuffer
50+)
51+
52+//line commit.qtpl:3
53+func StreamCommit(qw422016 *qt422016.Writer, name string, c *object.Commit) {
54+//line commit.qtpl:3
55+ qw422016.N().S(`
56+ <div class="row event">
57+ <div class="row">
58+ <div class="col-md">
59+ <a title="`)
60+//line commit.qtpl:7
61+ qw422016.E().S(c.Hash.String())
62+//line commit.qtpl:7
63+ qw422016.N().S(`" href="/`)
64+//line commit.qtpl:7
65+ qw422016.E().S(name)
66+//line commit.qtpl:7
67+ qw422016.N().S(`/commit/`)
68+//line commit.qtpl:7
69+ qw422016.E().S(c.Hash.String())
70+//line commit.qtpl:7
71+ qw422016.N().S(`">`)
72+//line commit.qtpl:7
73+ qw422016.E().S(c.Hash.String()[0:8])
74+//line commit.qtpl:7
75+ qw422016.N().S(`</a>
76+ </div>
77+ <div class="col-md text-md-end">
78+ <a title="`)
79+//line commit.qtpl:10
80+ qw422016.E().S(c.Committer.Email)
81+//line commit.qtpl:10
82+ qw422016.N().S(`" href="mailto:`)
83+//line commit.qtpl:10
84+ qw422016.E().S(c.Committer.Email)
85+//line commit.qtpl:10
86+ qw422016.N().S(`">`)
87+//line commit.qtpl:10
88+ qw422016.E().S(c.Committer.Name)
89+//line commit.qtpl:10
90+ qw422016.N().S(`</a>
91+ </div>
92+ </div>
93+ <div class="code-view">
94+ <pre>`)
95+//line commit.qtpl:14
96+ qw422016.E().S(c.Message)
97+//line commit.qtpl:14
98+ qw422016.N().S(`</pre>
99+ </div>
100+ </div>
101+`)
102+//line commit.qtpl:17
103+}
104+
105+//line commit.qtpl:17
106+func WriteCommit(qq422016 qtio422016.Writer, name string, c *object.Commit) {
107+//line commit.qtpl:17
108+ qw422016 := qt422016.AcquireWriter(qq422016)
109+//line commit.qtpl:17
110+ StreamCommit(qw422016, name, c)
111+//line commit.qtpl:17
112+ qt422016.ReleaseWriter(qw422016)
113+//line commit.qtpl:17
114+}
115+
116+//line commit.qtpl:17
117+func Commit(name string, c *object.Commit) string {
118+//line commit.qtpl:17
119+ qb422016 := qt422016.AcquireByteBuffer()
120+//line commit.qtpl:17
121+ WriteCommit(qb422016, name, c)
122+//line commit.qtpl:17
123+ qs422016 := string(qb422016.B)
124+//line commit.qtpl:17
125+ qt422016.ReleaseByteBuffer(qb422016)
126+//line commit.qtpl:17
127+ return qs422016
128+//line commit.qtpl:17
129+}
130diff --git a/templates/gititemlog.qtpl b/templates/gititemlog.qtpl
131index 3588d32403566a2b260c68d8d50c2b176671ad22..ee3841c25c6d12058955b1e3054f64cf2801837a 100644
132--- a/templates/gititemlog.qtpl
133+++ b/templates/gititemlog.qtpl
134@@ -11,18 +11,7 @@
135 {% func (g *GitItemLogPage) GitContent(name, ref string) %}
136 <div class="event-list">
137 {% for _, c := range g.Commits %}
138- <div class="row event">
139-
140- <div class="col-xxl-2">
141- {%s TimeFormat(c.Committer.When) %}
142- </div>
143- <div class="col-xxl-7 code-view">
144- <pre>{%s c.Message %}</pre>
145- </div>
146- <div class="col-xxl-3">
147- <small>{%s c.Committer.Name %} <{%s c.Committer.Email %}></small>
148- </div>
149- </div>
150+ {%= Commit(name, c) %}
151 {% endfor %}
152 </div>
153 {% endfunc %}
154diff --git a/templates/gititemlog.qtpl.go b/templates/gititemlog.qtpl.go
155index b950d1550a22169e8ca085849ca1ddad5dfb4aea..da8167aaed77dad2b6c6ea84a38e77ea9415f284 100644
156--- a/templates/gititemlog.qtpl.go
157+++ b/templates/gititemlog.qtpl.go
158@@ -68,66 +68,43 @@ //line gititemlog.qtpl:13
159 for _, c := range g.Commits {
160 //line gititemlog.qtpl:13
161 qw422016.N().S(`
162- <div class="row event">
163-
164- <div class="col-xxl-2">
165- `)
166-//line gititemlog.qtpl:17
167- qw422016.E().S(TimeFormat(c.Committer.When))
168-//line gititemlog.qtpl:17
169+ `)
170+//line gititemlog.qtpl:14
171+ StreamCommit(qw422016, name, c)
172+//line gititemlog.qtpl:14
173 qw422016.N().S(`
174- </div>
175- <div class="col-xxl-7 code-view">
176- <pre>`)
177-//line gititemlog.qtpl:20
178- qw422016.E().S(c.Message)
179-//line gititemlog.qtpl:20
180- qw422016.N().S(`</pre>
181- </div>
182- <div class="col-xxl-3">
183- <small>`)
184-//line gititemlog.qtpl:23
185- qw422016.E().S(c.Committer.Name)
186-//line gititemlog.qtpl:23
187- qw422016.N().S(` <`)
188-//line gititemlog.qtpl:23
189- qw422016.E().S(c.Committer.Email)
190-//line gititemlog.qtpl:23
191- qw422016.N().S(`></small>
192- </div>
193- </div>
194 `)
195-//line gititemlog.qtpl:26
196+//line gititemlog.qtpl:15
197 }
198-//line gititemlog.qtpl:26
199+//line gititemlog.qtpl:15
200 qw422016.N().S(`
201 </div>
202 `)
203-//line gititemlog.qtpl:28
204+//line gititemlog.qtpl:17
205 }
206
207-//line gititemlog.qtpl:28
208+//line gititemlog.qtpl:17
209 func (g *GitItemLogPage) WriteGitContent(qq422016 qtio422016.Writer, name, ref string) {
210-//line gititemlog.qtpl:28
211+//line gititemlog.qtpl:17
212 qw422016 := qt422016.AcquireWriter(qq422016)
213-//line gititemlog.qtpl:28
214+//line gititemlog.qtpl:17
215 g.StreamGitContent(qw422016, name, ref)
216-//line gititemlog.qtpl:28
217+//line gititemlog.qtpl:17
218 qt422016.ReleaseWriter(qw422016)
219-//line gititemlog.qtpl:28
220+//line gititemlog.qtpl:17
221 }
222
223-//line gititemlog.qtpl:28
224+//line gititemlog.qtpl:17
225 func (g *GitItemLogPage) GitContent(name, ref string) string {
226-//line gititemlog.qtpl:28
227+//line gititemlog.qtpl:17
228 qb422016 := qt422016.AcquireByteBuffer()
229-//line gititemlog.qtpl:28
230+//line gititemlog.qtpl:17
231 g.WriteGitContent(qb422016, name, ref)
232-//line gititemlog.qtpl:28
233+//line gititemlog.qtpl:17
234 qs422016 := string(qb422016.B)
235-//line gititemlog.qtpl:28
236+//line gititemlog.qtpl:17
237 qt422016.ReleaseByteBuffer(qb422016)
238-//line gititemlog.qtpl:28
239+//line gititemlog.qtpl:17
240 return qs422016
241-//line gititemlog.qtpl:28
242+//line gititemlog.qtpl:17
243 }
244diff --git a/templates/gititemsummary.qtpl b/templates/gititemsummary.qtpl
245index 06a785ad74913ce89927a32daff49b18529e9159..ef2c534df5b1d5ab85760c7de436b83d5f041e7c 100644
246--- a/templates/gititemsummary.qtpl
247+++ b/templates/gititemsummary.qtpl
248@@ -44,6 +44,7 @@ {%s b.Name().Short() %}
249 </div>
250 <div class="col-8">
251 <div class="float-end">
252+ <a href="/{%s name %}/archive/{%s b.Name().Short() %}.tar.gz">tar.gz</a>
253 <a href="/{%s name %}/tree/{%s b.Name().Short() %}/">tree</a>
254 <a href="/{%s name %}/log/{%s b.Name().Short() %}/">log</a>
255 </div>
256@@ -56,17 +57,7 @@ </div>
257 <div class="row">
258 <div class="event-list">
259 {% for _, c := range g.Commits %}
260- <div class="row event">
261- <div class="col-xxl-2">
262- {%s TimeFormat(c.Committer.When) %}
263- </div>
264- <div class="col-xxl-7 code-view">
265- <pre>{%s c.Message %}</pre>
266- </div>
267- <div class="col-xxl-3">
268- <small>{%s c.Committer.Name %} <{%s c.Committer.Email %}></small>
269- </div>
270- </div>
271+ {%= Commit(name, c) %}
272 {% endfor %}
273 </div>
274 </div>
275diff --git a/templates/gititemsummary.qtpl.go b/templates/gititemsummary.qtpl.go
276index 4e48efd0da70a6301114cfd65ef9929f96804953..570a95501376383761ed6eeaf38d4e7d25c765ad 100644
277--- a/templates/gititemsummary.qtpl.go
278+++ b/templates/gititemsummary.qtpl.go
279@@ -159,27 +159,36 @@ <a href="/`)
280 //line gititemsummary.qtpl:47
281 qw422016.E().S(name)
282 //line gititemsummary.qtpl:47
283- qw422016.N().S(`/tree/`)
284+ qw422016.N().S(`/archive/`)
285 //line gititemsummary.qtpl:47
286 qw422016.E().S(b.Name().Short())
287 //line gititemsummary.qtpl:47
288- qw422016.N().S(`/">tree</a>
289+ qw422016.N().S(`.tar.gz">tar.gz</a>
290 <a href="/`)
291 //line gititemsummary.qtpl:48
292 qw422016.E().S(name)
293 //line gititemsummary.qtpl:48
294- qw422016.N().S(`/log/`)
295+ qw422016.N().S(`/tree/`)
296 //line gititemsummary.qtpl:48
297 qw422016.E().S(b.Name().Short())
298 //line gititemsummary.qtpl:48
299+ qw422016.N().S(`/">tree</a>
300+ <a href="/`)
301+//line gititemsummary.qtpl:49
302+ qw422016.E().S(name)
303+//line gititemsummary.qtpl:49
304+ qw422016.N().S(`/log/`)
305+//line gititemsummary.qtpl:49
306+ qw422016.E().S(b.Name().Short())
307+//line gititemsummary.qtpl:49
308 qw422016.N().S(`/">log</a>
309 </div>
310 </div>
311 </div>
312 `)
313-//line gititemsummary.qtpl:52
314+//line gititemsummary.qtpl:53
315 }
316-//line gititemsummary.qtpl:52
317+//line gititemsummary.qtpl:53
318 qw422016.N().S(`
319 </div>
320 </div>
321@@ -187,70 +196,48 @@ </div>
322 <div class="row">
323 <div class="event-list">
324 `)
325-//line gititemsummary.qtpl:58
326+//line gititemsummary.qtpl:59
327 for _, c := range g.Commits {
328-//line gititemsummary.qtpl:58
329+//line gititemsummary.qtpl:59
330 qw422016.N().S(`
331- <div class="row event">
332- <div class="col-xxl-2">
333- `)
334-//line gititemsummary.qtpl:61
335- qw422016.E().S(TimeFormat(c.Committer.When))
336-//line gititemsummary.qtpl:61
337+ `)
338+//line gititemsummary.qtpl:60
339+ StreamCommit(qw422016, name, c)
340+//line gititemsummary.qtpl:60
341 qw422016.N().S(`
342- </div>
343- <div class="col-xxl-7 code-view">
344- <pre>`)
345-//line gititemsummary.qtpl:64
346- qw422016.E().S(c.Message)
347-//line gititemsummary.qtpl:64
348- qw422016.N().S(`</pre>
349- </div>
350- <div class="col-xxl-3">
351- <small>`)
352-//line gititemsummary.qtpl:67
353- qw422016.E().S(c.Committer.Name)
354-//line gititemsummary.qtpl:67
355- qw422016.N().S(` <`)
356-//line gititemsummary.qtpl:67
357- qw422016.E().S(c.Committer.Email)
358-//line gititemsummary.qtpl:67
359- qw422016.N().S(`></small>
360- </div>
361- </div>
362 `)
363-//line gititemsummary.qtpl:70
364+//line gititemsummary.qtpl:61
365 }
366-//line gititemsummary.qtpl:70
367+//line gititemsummary.qtpl:61
368 qw422016.N().S(`
369 </div>
370 </div>
371 `)
372-//line gititemsummary.qtpl:73
373+//line gititemsummary.qtpl:64
374 }
375
376-//line gititemsummary.qtpl:73
377+//line gititemsummary.qtpl:64
378 func (g *GitItemSummaryPage) WriteGitContent(qq422016 qtio422016.Writer, name, ref string) {
379-//line gititemsummary.qtpl:73
380+//line gititemsummary.qtpl:64
381 qw422016 := qt422016.AcquireWriter(qq422016)
382-//line gititemsummary.qtpl:73
383+//line gititemsummary.qtpl:64
384 g.StreamGitContent(qw422016, name, ref)
385-//line gititemsummary.qtpl:73
386+//line gititemsummary.qtpl:64
387 qt422016.ReleaseWriter(qw422016)
388-//line gititemsummary.qtpl:73
389+//line gititemsummary.qtpl:64
390 }
391
392-//line gititemsummary.qtpl:73
393+//line gititemsummary.qtpl:64
394 func (g *GitItemSummaryPage) GitContent(name, ref string) string {
395-//line gititemsummary.qtpl:73
396+//line gititemsummary.qtpl:64
397 qb422016 := qt422016.AcquireByteBuffer()
398-//line gititemsummary.qtpl:73
399+//line gititemsummary.qtpl:64
400 g.WriteGitContent(qb422016, name, ref)
401-//line gititemsummary.qtpl:73
402+//line gititemsummary.qtpl:64
403 qs422016 := string(qb422016.B)
404-//line gititemsummary.qtpl:73
405+//line gititemsummary.qtpl:64
406 qt422016.ReleaseByteBuffer(qb422016)
407-//line gititemsummary.qtpl:73
408+//line gititemsummary.qtpl:64
409 return qs422016
410-//line gititemsummary.qtpl:73
411+//line gititemsummary.qtpl:64
412 }