cerrado @ ce5185f551b707fe8dd8db8b5cbffd46e96cacc0

feat: Add per repository about page
  1diff --git a/pkg/config/config.go b/pkg/config/config.go
  2index 6ac6d0560dddf90e88fdce766d2a0261d5a4ab2c..3759b7cc65b14ec93b21b2e862e20b57248ca111 100644
  3--- a/pkg/config/config.go
  4+++ b/pkg/config/config.go
  5@@ -42,6 +42,7 @@ 		Name        string
  6 		Path        string
  7 		Description string
  8 		Public      bool
  9+		About       string
 10 	}
 11 
 12 	// ConfigurationRepository represents the configuration repository (as in
 13@@ -214,6 +215,10 @@ 			case "public":
 14 				if err := setBool(d, &repository.Public); err != nil {
 15 					return err
 16 				}
 17+			case "about":
 18+				if err := setString(d, &repository.About); err != nil {
 19+					return err
 20+				}
 21 			}
 22 		}
 23 
 24@@ -249,6 +254,7 @@ 		Path:        path,
 25 		Name:        filepath.Base(path),
 26 		Description: "",
 27 		Public:      false,
 28+		About:       "README.md",
 29 	}
 30 }
 31 
 32diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go
 33index 2d779c53ce9aee562d0e7d57e354b7470aa534de..8c1d27ebe8586e356314e45e6a5742766928b443 100644
 34--- a/pkg/config/config_test.go
 35+++ b/pkg/config/config_test.go
 36@@ -53,6 +53,7 @@ 						Name:        "cerrado.git",
 37 						Path:        "/srv/git/cerrado.git",
 38 						Description: "",
 39 						Public:      false,
 40+						About:       "README.md",
 41 					},
 42 				},
 43 			},
 44@@ -64,6 +65,7 @@ repository /srv/git/cerrado.git {
 45 	name cerrado
 46 	description "Single person forge"
 47 	public true
 48+	about readme.txt
 49 }`,
 50 			expectedConfig: &configuration{
 51 				Scan:       defaultScan(),
 52@@ -74,6 +76,7 @@ 						Name:        "cerrado",
 53 						Path:        "/srv/git/cerrado.git",
 54 						Description: "Single person forge",
 55 						Public:      true,
 56+						About:       "readme.txt",
 57 					},
 58 				},
 59 			},
 60@@ -111,6 +114,7 @@ repository /srv/git/cerrado.git {
 61 	name cerrado
 62 	description "Single person forge"
 63 	public true
 64+	about readme.txt
 65 }`,
 66 			expectedConfig: &configuration{
 67 				Scan: &scan{
 68@@ -124,12 +128,14 @@ 						Name:        "linux.git",
 69 						Path:        "/srv/git/linux.git",
 70 						Description: "",
 71 						Public:      false,
 72+						About:       "README.md",
 73 					},
 74 					{
 75 						Name:        "cerrado",
 76 						Path:        "/srv/git/cerrado.git",
 77 						Description: "Single person forge",
 78 						Public:      true,
 79+						About:       "readme.txt",
 80 					},
 81 				},
 82 			},
 83diff --git a/pkg/handler/git/handler.go b/pkg/handler/git/handler.go
 84index 899f61ee30eab7f322c42d25636de59791763221..25505ba4c8ebfc520f69f9e21b87eef41752cd66 100644
 85--- a/pkg/handler/git/handler.go
 86+++ b/pkg/handler/git/handler.go
 87@@ -33,6 +33,7 @@ 		ListCommits(name string, ref string, count int) ([]*object.Commit, error)
 88 		GetHead(name string) (*plumbing.Reference, error)
 89 		GetTree(name, ref, path string) (*object.Tree, error)
 90 		GetFileContent(name, ref, path string) (string, error)
 91+		GetAbout(name string) (string, error)
 92 		ListTags(name string) ([]*plumbing.Reference, error)
 93 		ListBranches(name string) ([]*plumbing.Reference, error)
 94 	}
 95@@ -126,10 +127,28 @@ 	ref, err := g.gitService.GetHead(name)
 96 	if err != nil {
 97 		return err
 98 	}
 99+
100+	file, err := g.gitService.GetAbout(name)
101+	if err != nil {
102+		return err
103+	}
104+
105+	extensions := parser.CommonExtensions | parser.AutoHeadingIDs | parser.NoEmptyLineBeforeBlock
106+	p := parser.NewWithExtensions(extensions)
107+	doc := p.Parse([]byte(file))
108+
109+	htmlFlag := markdownhtml.CommonFlags | markdownhtml.HrefTargetBlank
110+	opts := markdownhtml.RendererOptions{Flags: htmlFlag}
111+	renderer := markdownhtml.NewRenderer(opts)
112+
113+	bs := markdown.Render(doc, renderer)
114+
115 	gitList := &templates.GitItemPage{
116-		Name:        name,
117-		Ref:         ref.Name().Short(),
118-		GitItemBase: &templates.GitItemAboutPage{},
119+		Name: name,
120+		Ref:  ref.Name().Short(),
121+		GitItemBase: &templates.GitItemAboutPage{
122+			About: bs,
123+		},
124 	}
125 	templates.WritePageTemplate(w, gitList)
126 	return nil
127diff --git a/pkg/service/git.go b/pkg/service/git.go
128index 2165abef8acdfbe13d4831c7e6e0c2556678b004..6bb6e9ebb7739ae025c124766ac402d19c429aad 100644
129--- a/pkg/service/git.go
130+++ b/pkg/service/git.go
131@@ -128,6 +128,24 @@
132 	return repo.FileContent(path)
133 }
134 
135+func (g *GitService) GetAbout(name string) (string, error) {
136+	r := g.configRepo.GetByName(name)
137+	if r == nil {
138+		return "", RepositoryNotFoundErr
139+	}
140+
141+	repo, err := git.OpenRepository(r.Path)
142+	if err != nil {
143+		return "", err
144+	}
145+	err = repo.SetRef("")
146+	if err != nil {
147+		return "", err
148+	}
149+
150+	return repo.FileContent(r.About)
151+}
152+
153 func (g *GitService) ListTags(name string) ([]*plumbing.Reference, error) {
154 	r := g.configRepo.GetByName(name)
155 	if r == nil {
156diff --git a/scss/main.scss b/scss/main.scss
157index 107a4c8231a96c66e05ffc6cc91dda311568a367..c438a906e17ffab32f1ce85550253e1b7ea74847 100644
158--- a/scss/main.scss
159+++ b/scss/main.scss
160@@ -60,6 +60,12 @@       end: right,
161       center: center,
162     )
163   ),
164+  "margin": (
165+    responsive: true,
166+    property: margin,
167+    class: m,
168+    values: map-merge($spacers, (auto: auto))
169+  ),
170   "margin-end": (
171     responsive: true,
172     property: margin-right,
173@@ -110,6 +116,11 @@   margin: 0.5rem 0;
174 }
175 
176 .code-view {
177+    display: grid;
178+    overflow-x: auto;
179+}
180+
181+pre {
182     display: grid;
183     overflow-x: auto;
184 }
185diff --git a/templates/gititemabout.qtpl b/templates/gititemabout.qtpl
186index abda2fb2476cf828c66e19736aea6e857feac0fd..da9c2e963053111c905671375f028ebf95b1123b 100644
187--- a/templates/gititemabout.qtpl
188+++ b/templates/gititemabout.qtpl
189@@ -1,10 +1,13 @@
190 {% code
191 type GitItemAboutPage struct {
192+    About []byte
193 }
194 %}
195 
196 {% func (g *GitItemAboutPage) Nav(name, ref string) %}{%= GitItemNav(name, ref, Readme) %}{% endfunc %}
197 
198 {% func (g *GitItemAboutPage) GitContent(name, ref string) %}
199-<h4>About</h4>
200+<div class="m-2">
201+{%z= g.About %}
202+</div>
203 {% endfunc %}
204diff --git a/templates/gititemabout.qtpl.go b/templates/gititemabout.qtpl.go
205index cd49d2fa25928890cb2a8e6ccda5d5057f1144e0..e1c1db423a94f90e4a9fb1d3563acfbdca7c9698 100644
206--- a/templates/gititemabout.qtpl.go
207+++ b/templates/gititemabout.qtpl.go
208@@ -19,72 +19,79 @@ )
209 
210 //line gititemabout.qtpl:2
211 type GitItemAboutPage struct {
212+	About []byte
213 }
214 
215-//line gititemabout.qtpl:6
216+//line gititemabout.qtpl:7
217 func (g *GitItemAboutPage) StreamNav(qw422016 *qt422016.Writer, name, ref string) {
218-//line gititemabout.qtpl:6
219+//line gititemabout.qtpl:7
220 	StreamGitItemNav(qw422016, name, ref, Readme)
221-//line gititemabout.qtpl:6
222+//line gititemabout.qtpl:7
223 }
224 
225-//line gititemabout.qtpl:6
226+//line gititemabout.qtpl:7
227 func (g *GitItemAboutPage) WriteNav(qq422016 qtio422016.Writer, name, ref string) {
228-//line gititemabout.qtpl:6
229+//line gititemabout.qtpl:7
230 	qw422016 := qt422016.AcquireWriter(qq422016)
231-//line gititemabout.qtpl:6
232+//line gititemabout.qtpl:7
233 	g.StreamNav(qw422016, name, ref)
234-//line gititemabout.qtpl:6
235+//line gititemabout.qtpl:7
236 	qt422016.ReleaseWriter(qw422016)
237-//line gititemabout.qtpl:6
238+//line gititemabout.qtpl:7
239 }
240 
241-//line gititemabout.qtpl:6
242+//line gititemabout.qtpl:7
243 func (g *GitItemAboutPage) Nav(name, ref string) string {
244-//line gititemabout.qtpl:6
245+//line gititemabout.qtpl:7
246 	qb422016 := qt422016.AcquireByteBuffer()
247-//line gititemabout.qtpl:6
248+//line gititemabout.qtpl:7
249 	g.WriteNav(qb422016, name, ref)
250-//line gititemabout.qtpl:6
251+//line gititemabout.qtpl:7
252 	qs422016 := string(qb422016.B)
253-//line gititemabout.qtpl:6
254+//line gititemabout.qtpl:7
255 	qt422016.ReleaseByteBuffer(qb422016)
256-//line gititemabout.qtpl:6
257+//line gititemabout.qtpl:7
258 	return qs422016
259-//line gititemabout.qtpl:6
260+//line gititemabout.qtpl:7
261 }
262 
263-//line gititemabout.qtpl:8
264+//line gititemabout.qtpl:9
265 func (g *GitItemAboutPage) StreamGitContent(qw422016 *qt422016.Writer, name, ref string) {
266-//line gititemabout.qtpl:8
267+//line gititemabout.qtpl:9
268+	qw422016.N().S(`
269+<div class="m-2">
270+`)
271+//line gititemabout.qtpl:11
272+	qw422016.N().Z(g.About)
273+//line gititemabout.qtpl:11
274 	qw422016.N().S(`
275-<h4>About</h4>
276+</div>
277 `)
278-//line gititemabout.qtpl:10
279+//line gititemabout.qtpl:13
280 }
281 
282-//line gititemabout.qtpl:10
283+//line gititemabout.qtpl:13
284 func (g *GitItemAboutPage) WriteGitContent(qq422016 qtio422016.Writer, name, ref string) {
285-//line gititemabout.qtpl:10
286+//line gititemabout.qtpl:13
287 	qw422016 := qt422016.AcquireWriter(qq422016)
288-//line gititemabout.qtpl:10
289+//line gititemabout.qtpl:13
290 	g.StreamGitContent(qw422016, name, ref)
291-//line gititemabout.qtpl:10
292+//line gititemabout.qtpl:13
293 	qt422016.ReleaseWriter(qw422016)
294-//line gititemabout.qtpl:10
295+//line gititemabout.qtpl:13
296 }
297 
298-//line gititemabout.qtpl:10
299+//line gititemabout.qtpl:13
300 func (g *GitItemAboutPage) GitContent(name, ref string) string {
301-//line gititemabout.qtpl:10
302+//line gititemabout.qtpl:13
303 	qb422016 := qt422016.AcquireByteBuffer()
304-//line gititemabout.qtpl:10
305+//line gititemabout.qtpl:13
306 	g.WriteGitContent(qb422016, name, ref)
307-//line gititemabout.qtpl:10
308+//line gititemabout.qtpl:13
309 	qs422016 := string(qb422016.B)
310-//line gititemabout.qtpl:10
311+//line gititemabout.qtpl:13
312 	qt422016.ReleaseByteBuffer(qb422016)
313-//line gititemabout.qtpl:10
314+//line gititemabout.qtpl:13
315 	return qs422016
316-//line gititemabout.qtpl:10
317+//line gititemabout.qtpl:13
318 }
319diff --git a/templates/gititemlog.qtpl b/templates/gititemlog.qtpl
320index a28e7ad52cbd51c2cb6509b3f008116b61e7d8be..3588d32403566a2b260c68d8d50c2b176671ad22 100644
321--- a/templates/gititemlog.qtpl
322+++ b/templates/gititemlog.qtpl
323@@ -12,6 +12,7 @@ {% func (g *GitItemLogPage) GitContent(name, ref string) %}
324 <div class="event-list">
325   {% for _, c := range g.Commits %}
326   <div class="row event">
327+
328       <div class="col-xxl-2">
329        {%s TimeFormat(c.Committer.When) %}
330       </div>
331diff --git a/templates/gititemlog.qtpl.go b/templates/gititemlog.qtpl.go
332index 76c24329c241285809f56a6a9014e1e4274d47bb..b950d1550a22169e8ca085849ca1ddad5dfb4aea 100644
333--- a/templates/gititemlog.qtpl.go
334+++ b/templates/gititemlog.qtpl.go
335@@ -69,64 +69,65 @@ 	for _, c := range g.Commits {
336 //line gititemlog.qtpl:13
337 		qw422016.N().S(`
338   <div class="row event">
339+
340       <div class="col-xxl-2">
341        `)
342-//line gititemlog.qtpl:16
343+//line gititemlog.qtpl:17
344 		qw422016.E().S(TimeFormat(c.Committer.When))
345-//line gititemlog.qtpl:16
346+//line gititemlog.qtpl:17
347 		qw422016.N().S(`
348       </div>
349       <div class="col-xxl-7 code-view">
350        <pre>`)
351-//line gititemlog.qtpl:19
352+//line gititemlog.qtpl:20
353 		qw422016.E().S(c.Message)
354-//line gititemlog.qtpl:19
355+//line gititemlog.qtpl:20
356 		qw422016.N().S(`</pre>
357       </div>
358       <div class="col-xxl-3">
359        <small>`)
360-//line gititemlog.qtpl:22
361+//line gititemlog.qtpl:23
362 		qw422016.E().S(c.Committer.Name)
363-//line gititemlog.qtpl:22
364+//line gititemlog.qtpl:23
365 		qw422016.N().S(` &lt;`)
366-//line gititemlog.qtpl:22
367+//line gititemlog.qtpl:23
368 		qw422016.E().S(c.Committer.Email)
369-//line gititemlog.qtpl:22
370+//line gititemlog.qtpl:23
371 		qw422016.N().S(`&gt;</small>
372       </div>
373   </div>
374   `)
375-//line gititemlog.qtpl:25
376+//line gititemlog.qtpl:26
377 	}
378-//line gititemlog.qtpl:25
379+//line gititemlog.qtpl:26
380 	qw422016.N().S(`
381 </div>
382 `)
383-//line gititemlog.qtpl:27
384+//line gititemlog.qtpl:28
385 }
386 
387-//line gititemlog.qtpl:27
388+//line gititemlog.qtpl:28
389 func (g *GitItemLogPage) WriteGitContent(qq422016 qtio422016.Writer, name, ref string) {
390-//line gititemlog.qtpl:27
391+//line gititemlog.qtpl:28
392 	qw422016 := qt422016.AcquireWriter(qq422016)
393-//line gititemlog.qtpl:27
394+//line gititemlog.qtpl:28
395 	g.StreamGitContent(qw422016, name, ref)
396-//line gititemlog.qtpl:27
397+//line gititemlog.qtpl:28
398 	qt422016.ReleaseWriter(qw422016)
399-//line gititemlog.qtpl:27
400+//line gititemlog.qtpl:28
401 }
402 
403-//line gititemlog.qtpl:27
404+//line gititemlog.qtpl:28
405 func (g *GitItemLogPage) GitContent(name, ref string) string {
406-//line gititemlog.qtpl:27
407+//line gititemlog.qtpl:28
408 	qb422016 := qt422016.AcquireByteBuffer()
409-//line gititemlog.qtpl:27
410+//line gititemlog.qtpl:28
411 	g.WriteGitContent(qb422016, name, ref)
412-//line gititemlog.qtpl:27
413+//line gititemlog.qtpl:28
414 	qs422016 := string(qb422016.B)
415-//line gititemlog.qtpl:27
416+//line gititemlog.qtpl:28
417 	qt422016.ReleaseByteBuffer(qb422016)
418-//line gititemlog.qtpl:27
419+//line gititemlog.qtpl:28
420 	return qs422016
421-//line gititemlog.qtpl:27
422+//line gititemlog.qtpl:28
423 }