apkdoc @ 33727db8bee991115906d3408145d5e0806a2455

feat: Add initial template renderer for markdown
  1diff --git a/Makefile b/Makefile
  2index e3ed19e0cdbc143c4992c36be62a00cf8cd29b11..0c1a1f65bd08e64ab7d5342576176d22fc145fbf 100644
  3--- a/Makefile
  4+++ b/Makefile
  5@@ -4,10 +4,14 @@ GO_BUILD?= go build -v
  6 
  7 all: build
  8 
  9-run:
 10+run: tmpl
 11 	$(GO_RUN) .
 12 
 13-build:
 14+build: tmpl
 15 	$(GO_BUILD) \
 16 		-o bin/$(BIN) \
 17 		.
 18+
 19+tmpl:
 20+	cd ./templates && \
 21+	qtc *
 22diff --git a/go.mod b/go.mod
 23index ccd8d0788985ebaa95e48f2be71765140b01fd93..6ec9ad4c3ea0771cc12e0f0a3feadff13616085b 100644
 24--- a/go.mod
 25+++ b/go.mod
 26@@ -1,3 +1,8 @@
 27 module git.sr.ht/~gabrielgio/apkdoc
 28 
 29 go 1.20
 30+
 31+require (
 32+	github.com/valyala/bytebufferpool v1.0.0 // indirect
 33+	github.com/valyala/quicktemplate v1.7.0 // indirect
 34+)
 35diff --git a/go.sum b/go.sum
 36new file mode 100644
 37index 0000000000000000000000000000000000000000..9b4d04803e4106351206e0a5975f5da6faffd9f0
 38--- /dev/null
 39+++ b/go.sum
 40@@ -0,0 +1,21 @@
 41+github.com/andybalholm/brotli v1.0.2/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
 42+github.com/andybalholm/brotli v1.0.3/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
 43+github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
 44+github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
 45+github.com/klauspost/compress v1.13.5/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
 46+github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
 47+github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
 48+github.com/valyala/fasthttp v1.30.0/go.mod h1:2rsYD01CKFrjjsvFxx75KlEUNpWNBY9JWD3K/7o2Cus=
 49+github.com/valyala/quicktemplate v1.7.0 h1:LUPTJmlVcb46OOUY3IeD9DojFpAVbsG+5WFTcjMJzCM=
 50+github.com/valyala/quicktemplate v1.7.0/go.mod h1:sqKJnoaOF88V07vkO+9FL8fb9uZg/VPSJnLYn+LmLk8=
 51+github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
 52+golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
 53+golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 54+golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 55+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 56+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 57+golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 58+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 59+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 60+golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 61+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 62diff --git a/main.go b/main.go
 63index 9e64dbb8cf255a51a31e830010f39b975e214188..cfc56c4e483d0a58972fda410b6a563f45629d71 100644
 64--- a/main.go
 65+++ b/main.go
 66@@ -6,9 +6,12 @@ 	"bufio"
 67 	"compress/gzip"
 68 	"errors"
 69 	"flag"
 70-	"fmt"
 71 	"io"
 72 	"net/http"
 73+	"os"
 74+
 75+	"git.sr.ht/~gabrielgio/apkdoc/parser"
 76+	"git.sr.ht/~gabrielgio/apkdoc/templates"
 77 )
 78 
 79 func fechIndex(url string) (io.ReadCloser, error) {
 80@@ -26,6 +29,7 @@ }
 81 
 82 func main() {
 83 	url := flag.String("url", "", "Url to the APKINDEX.tar.gz")
 84+	output := flag.String("output", "index.md", "Output path")
 85 	flag.Parse()
 86 
 87 	tarStream, err := fechIndex(*url)
 88@@ -55,13 +59,13 @@ 	}
 89 
 90 	s := bufio.NewScanner(tr)
 91 
 92-	entries := make([]*Entry, 0)
 93+	entries := make([]*parser.Entry, 0)
 94 	lines := make([]string, 0)
 95 
 96 	for s.Scan() {
 97 		l := s.Text()
 98 		if l == "" {
 99-			entry := Parse(lines)
100+			entry := parser.Parse(lines)
101 			entries = append(entries, entry)
102 			lines = make([]string, 0)
103 		} else {
104@@ -69,7 +73,10 @@ 			lines = append(lines, l)
105 		}
106 	}
107 
108-	for _, e := range entries {
109-		fmt.Printf("%+v\n", e)
110+	file, err := os.Create(*output)
111+	if err != nil {
112+		panic("Error opening output file: " + err.Error())
113 	}
114+
115+	templates.WriteMarkdownTemplate(file, entries)
116 }
117diff --git a/parser.go b/parser/parser.go
118rename from parser.go
119rename to parser/parser.go
120index 998df918ed8f8749db4ccde332ca1c3b61317405..8996b8cd81c06890f565e445197e6a8fbc4db895 100644
121--- a/parser.go
122+++ b/parser/parser.go
123@@ -1,4 +1,4 @@
124-package main
125+package parser
126 
127 import (
128 	"strconv"
129@@ -10,10 +10,11 @@ type (
130 	// https://wiki.alpinelinux.org/wiki/Apk_spec
131 	Entry struct {
132 		Checksum         string     // C
133+		Version          string     // V
134 		Name             string     // P
135 		Architecture     *string    // A
136 		PackageSize      int        // S
137-		InstalledSize    *int       // I
138+		InstalledSize    int        // I
139 		Description      string     // T
140 		Url              string     // U
141 		License          string     // L
142@@ -49,6 +50,8 @@ 		r, c := split(line)
143 		switch r {
144 		case "C":
145 			entry.Checksum = c
146+		case "V":
147+			entry.Version = c
148 		case "P":
149 			entry.Name = c
150 		case "A":
151@@ -56,7 +59,7 @@ 			entry.Architecture = &c
152 		case "S":
153 			entry.PackageSize = toInt(c)
154 		case "I":
155-			entry.InstalledSize = ptr(toInt(c))
156+			entry.InstalledSize = toInt(c)
157 		case "T":
158 			entry.Description = c
159 		case "U":
160diff --git a/templates/index.md.qtpl b/templates/index.md.qtpl
161new file mode 100644
162index 0000000000000000000000000000000000000000..879795a6f96627cd2575cb99092d6718be4c4486
163--- /dev/null
164+++ b/templates/index.md.qtpl
165@@ -0,0 +1,33 @@
166+{% import "git.sr.ht/~gabrielgio/apkdoc/parser" %}
167+{% import "strings" %}
168+
169+{% code 
170+func reduce(lines []string) string {
171+    return strings.Join(lines, " ")
172+}
173+%}
174+
175+{% func MarkdownTemplate(entries []*parser.Entry) %}
176+# Apks Alpine 3.18
177+{% for _, e := range entries %}
178+## {%s e.Name %}
179+
180+**Version**: {%s e.Version%}
181+**Description**: {%s e.Description%}
182+{% if e.Maintainer != nil %}**Maintainer**: {%s *e.Maintainer%}{% endif %}
183+**Checksum**:{%s e.Checksum%}
184+{% if e.Architecture != nil %}**Architecture**: {%s *e.Architecture%}{% endif %}
185+**Size**: {%d e.PackageSize%}B
186+**Installed size**: {%d e.InstalledSize%}
187+**Url**: {%s e.Url%}
188+**License**: {%s e.License%}
189+{% if e.Origin != nil %}**Origin**: {%s *e.Origin%}{% endif %}
190+{% if e.BuildTime != nil %}**Build time**: {%s e.BuildTime.String() %}{% endif %}
191+{% if e.Commit != nil %}**Commit**: {%s *e.Commit %}{% endif %}
192+{% if e.ProviderPriority != nil %}**Provider Priority**: {%d *e.ProviderPriority %}{% endif %}
193+{% if len(e.Dependencies) > 0 %}**Dependencies:**: {%s reduce(e.Dependencies) %}{% endif %}
194+{% if len(e.Provides) > 0 %}**Provides:**: {%s reduce(e.Provides) %}{% endif %}
195+{% if len(e.InstallIf) > 0 %}**Install if:**: {%s reduce(e.InstallIf) %}{% endif %}
196+{% endfor %}
197+
198+{% endfunc %}
199diff --git a/templates/index.md.qtpl.go b/templates/index.md.qtpl.go
200new file mode 100644
201index 0000000000000000000000000000000000000000..af3d34a5d9a07cdd2e9a370ac306523268c03092
202--- /dev/null
203+++ b/templates/index.md.qtpl.go
204@@ -0,0 +1,215 @@
205+// Code generated by qtc from "index.md.qtpl". DO NOT EDIT.
206+// See https://github.com/valyala/quicktemplate for details.
207+
208+//line index.md.qtpl:1
209+package templates
210+
211+//line index.md.qtpl:1
212+import "git.sr.ht/~gabrielgio/apkdoc/parser"
213+
214+//line index.md.qtpl:2
215+import "strings"
216+
217+//line index.md.qtpl:4
218+import (
219+	qtio422016 "io"
220+
221+	qt422016 "github.com/valyala/quicktemplate"
222+)
223+
224+//line index.md.qtpl:4
225+var (
226+	_ = qtio422016.Copy
227+	_ = qt422016.AcquireByteBuffer
228+)
229+
230+//line index.md.qtpl:5
231+func reduce(lines []string) string {
232+	return strings.Join(lines, " ")
233+}
234+
235+//line index.md.qtpl:10
236+func StreamMarkdownTemplate(qw422016 *qt422016.Writer, entries []*parser.Entry) {
237+//line index.md.qtpl:10
238+	qw422016.N().S(`
239+# Apks Alpine 3.18
240+`)
241+//line index.md.qtpl:12
242+	for _, e := range entries {
243+//line index.md.qtpl:12
244+		qw422016.N().S(`
245+## `)
246+//line index.md.qtpl:13
247+		qw422016.E().S(e.Name)
248+//line index.md.qtpl:13
249+		qw422016.N().S(`
250+
251+**Version**: `)
252+//line index.md.qtpl:15
253+		qw422016.E().S(e.Version)
254+//line index.md.qtpl:15
255+		qw422016.N().S(`
256+**Description**: `)
257+//line index.md.qtpl:16
258+		qw422016.E().S(e.Description)
259+//line index.md.qtpl:16
260+		qw422016.N().S(`
261+`)
262+//line index.md.qtpl:17
263+		if e.Maintainer != nil {
264+//line index.md.qtpl:17
265+			qw422016.N().S(`**Maintainer**: `)
266+//line index.md.qtpl:17
267+			qw422016.E().S(*e.Maintainer)
268+//line index.md.qtpl:17
269+		}
270+//line index.md.qtpl:17
271+		qw422016.N().S(`
272+**Checksum**:`)
273+//line index.md.qtpl:18
274+		qw422016.E().S(e.Checksum)
275+//line index.md.qtpl:18
276+		qw422016.N().S(`
277+`)
278+//line index.md.qtpl:19
279+		if e.Architecture != nil {
280+//line index.md.qtpl:19
281+			qw422016.N().S(`**Architecture**: `)
282+//line index.md.qtpl:19
283+			qw422016.E().S(*e.Architecture)
284+//line index.md.qtpl:19
285+		}
286+//line index.md.qtpl:19
287+		qw422016.N().S(`
288+**Size**: `)
289+//line index.md.qtpl:20
290+		qw422016.N().D(e.PackageSize)
291+//line index.md.qtpl:20
292+		qw422016.N().S(`B
293+**Installed size**: `)
294+//line index.md.qtpl:21
295+		qw422016.N().D(e.InstalledSize)
296+//line index.md.qtpl:21
297+		qw422016.N().S(`
298+**Url**: `)
299+//line index.md.qtpl:22
300+		qw422016.E().S(e.Url)
301+//line index.md.qtpl:22
302+		qw422016.N().S(`
303+**License**: `)
304+//line index.md.qtpl:23
305+		qw422016.E().S(e.License)
306+//line index.md.qtpl:23
307+		qw422016.N().S(`
308+`)
309+//line index.md.qtpl:24
310+		if e.Origin != nil {
311+//line index.md.qtpl:24
312+			qw422016.N().S(`**Origin**: `)
313+//line index.md.qtpl:24
314+			qw422016.E().S(*e.Origin)
315+//line index.md.qtpl:24
316+		}
317+//line index.md.qtpl:24
318+		qw422016.N().S(`
319+`)
320+//line index.md.qtpl:25
321+		if e.BuildTime != nil {
322+//line index.md.qtpl:25
323+			qw422016.N().S(`**Build time**: `)
324+//line index.md.qtpl:25
325+			qw422016.E().S(e.BuildTime.String())
326+//line index.md.qtpl:25
327+		}
328+//line index.md.qtpl:25
329+		qw422016.N().S(`
330+`)
331+//line index.md.qtpl:26
332+		if e.Commit != nil {
333+//line index.md.qtpl:26
334+			qw422016.N().S(`**Commit**: `)
335+//line index.md.qtpl:26
336+			qw422016.E().S(*e.Commit)
337+//line index.md.qtpl:26
338+		}
339+//line index.md.qtpl:26
340+		qw422016.N().S(`
341+`)
342+//line index.md.qtpl:27
343+		if e.ProviderPriority != nil {
344+//line index.md.qtpl:27
345+			qw422016.N().S(`**Provider Priority**: `)
346+//line index.md.qtpl:27
347+			qw422016.N().D(*e.ProviderPriority)
348+//line index.md.qtpl:27
349+		}
350+//line index.md.qtpl:27
351+		qw422016.N().S(`
352+`)
353+//line index.md.qtpl:28
354+		if len(e.Dependencies) > 0 {
355+//line index.md.qtpl:28
356+			qw422016.N().S(`**Dependencies:**: `)
357+//line index.md.qtpl:28
358+			qw422016.E().S(reduce(e.Dependencies))
359+//line index.md.qtpl:28
360+		}
361+//line index.md.qtpl:28
362+		qw422016.N().S(`
363+`)
364+//line index.md.qtpl:29
365+		if len(e.Provides) > 0 {
366+//line index.md.qtpl:29
367+			qw422016.N().S(`**Provides:**: `)
368+//line index.md.qtpl:29
369+			qw422016.E().S(reduce(e.Provides))
370+//line index.md.qtpl:29
371+		}
372+//line index.md.qtpl:29
373+		qw422016.N().S(`
374+`)
375+//line index.md.qtpl:30
376+		if len(e.InstallIf) > 0 {
377+//line index.md.qtpl:30
378+			qw422016.N().S(`**Install if:**: `)
379+//line index.md.qtpl:30
380+			qw422016.E().S(reduce(e.InstallIf))
381+//line index.md.qtpl:30
382+		}
383+//line index.md.qtpl:30
384+		qw422016.N().S(`
385+`)
386+//line index.md.qtpl:31
387+	}
388+//line index.md.qtpl:31
389+	qw422016.N().S(`
390+
391+`)
392+//line index.md.qtpl:33
393+}
394+
395+//line index.md.qtpl:33
396+func WriteMarkdownTemplate(qq422016 qtio422016.Writer, entries []*parser.Entry) {
397+//line index.md.qtpl:33
398+	qw422016 := qt422016.AcquireWriter(qq422016)
399+//line index.md.qtpl:33
400+	StreamMarkdownTemplate(qw422016, entries)
401+//line index.md.qtpl:33
402+	qt422016.ReleaseWriter(qw422016)
403+//line index.md.qtpl:33
404+}
405+
406+//line index.md.qtpl:33
407+func MarkdownTemplate(entries []*parser.Entry) string {
408+//line index.md.qtpl:33
409+	qb422016 := qt422016.AcquireByteBuffer()
410+//line index.md.qtpl:33
411+	WriteMarkdownTemplate(qb422016, entries)
412+//line index.md.qtpl:33
413+	qs422016 := string(qb422016.B)
414+//line index.md.qtpl:33
415+	qt422016.ReleaseByteBuffer(qb422016)
416+//line index.md.qtpl:33
417+	return qs422016
418+//line index.md.qtpl:33
419+}