From 33727db8bee991115906d3408145d5e0806a2455 Mon Sep 17 00:00:00 2001 From: Gabriel Arakaki Giovanini Date: Sat, 26 Aug 2023 21:47:47 +0200 Subject: feat: Add initial template renderer for markdown --- Makefile | 8 +- go.mod | 5 ++ go.sum | 21 +++++ main.go | 17 ++-- parser.go | 85 ------------------ parser/parser.go | 88 +++++++++++++++++++ templates/index.md.qtpl | 33 +++++++ templates/index.md.qtpl.go | 215 +++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 380 insertions(+), 92 deletions(-) create mode 100644 go.sum delete mode 100644 parser.go create mode 100644 parser/parser.go create mode 100644 templates/index.md.qtpl create mode 100644 templates/index.md.qtpl.go diff --git a/Makefile b/Makefile index e3ed19e..0c1a1f6 100644 --- a/Makefile +++ b/Makefile @@ -4,10 +4,14 @@ GO_BUILD?= go build -v all: build -run: +run: tmpl $(GO_RUN) . -build: +build: tmpl $(GO_BUILD) \ -o bin/$(BIN) \ . + +tmpl: + cd ./templates && \ + qtc * diff --git a/go.mod b/go.mod index ccd8d07..6ec9ad4 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,8 @@ module git.sr.ht/~gabrielgio/apkdoc go 1.20 + +require ( + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/valyala/quicktemplate v1.7.0 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..9b4d048 --- /dev/null +++ b/go.sum @@ -0,0 +1,21 @@ +github.com/andybalholm/brotli v1.0.2/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= +github.com/andybalholm/brotli v1.0.3/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= +github.com/klauspost/compress v1.13.5/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasthttp v1.30.0/go.mod h1:2rsYD01CKFrjjsvFxx75KlEUNpWNBY9JWD3K/7o2Cus= +github.com/valyala/quicktemplate v1.7.0 h1:LUPTJmlVcb46OOUY3IeD9DojFpAVbsG+5WFTcjMJzCM= +github.com/valyala/quicktemplate v1.7.0/go.mod h1:sqKJnoaOF88V07vkO+9FL8fb9uZg/VPSJnLYn+LmLk8= +github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= +golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/main.go b/main.go index 9e64dbb..cfc56c4 100644 --- a/main.go +++ b/main.go @@ -6,9 +6,12 @@ import ( "compress/gzip" "errors" "flag" - "fmt" "io" "net/http" + "os" + + "git.sr.ht/~gabrielgio/apkdoc/parser" + "git.sr.ht/~gabrielgio/apkdoc/templates" ) func fechIndex(url string) (io.ReadCloser, error) { @@ -26,6 +29,7 @@ func fechIndex(url string) (io.ReadCloser, error) { func main() { url := flag.String("url", "", "Url to the APKINDEX.tar.gz") + output := flag.String("output", "index.md", "Output path") flag.Parse() tarStream, err := fechIndex(*url) @@ -55,13 +59,13 @@ func main() { s := bufio.NewScanner(tr) - entries := make([]*Entry, 0) + entries := make([]*parser.Entry, 0) lines := make([]string, 0) for s.Scan() { l := s.Text() if l == "" { - entry := Parse(lines) + entry := parser.Parse(lines) entries = append(entries, entry) lines = make([]string, 0) } else { @@ -69,7 +73,10 @@ func main() { } } - for _, e := range entries { - fmt.Printf("%+v\n", e) + file, err := os.Create(*output) + if err != nil { + panic("Error opening output file: " + err.Error()) } + + templates.WriteMarkdownTemplate(file, entries) } diff --git a/parser.go b/parser.go deleted file mode 100644 index 998df91..0000000 --- a/parser.go +++ /dev/null @@ -1,85 +0,0 @@ -package main - -import ( - "strconv" - "strings" - "time" -) - -type ( - // https://wiki.alpinelinux.org/wiki/Apk_spec - Entry struct { - Checksum string // C - Name string // P - Architecture *string // A - PackageSize int // S - InstalledSize *int // I - Description string // T - Url string // U - License string // L - Origin *string // o - Maintainer *string // m - BuildTime *time.Time // t - Commit *string // c - ProviderPriority *int // k - Dependencies []string // D - Provides []string // p - InstallIf []string // i - } -) - -func ptr[T any](v T) *T { - return &v -} - -func split(line string) (string, string) { - parts := strings.SplitN(line, ":", 2) - return parts[0], parts[1] -} - -func toInt(v string) int { - i, _ := strconv.Atoi(v) - return i -} - -func Parse(lines []string) *Entry { - entry := &Entry{} - for _, line := range lines { - r, c := split(line) - switch r { - case "C": - entry.Checksum = c - case "P": - entry.Name = c - case "A": - entry.Architecture = &c - case "S": - entry.PackageSize = toInt(c) - case "I": - entry.InstalledSize = ptr(toInt(c)) - case "T": - entry.Description = c - case "U": - entry.Url = c - case "L": - entry.License = c - case "o": - entry.Origin = &c - case "m": - entry.Maintainer = &c - case "t": - entry.BuildTime = ptr(time.Unix(int64(toInt(c)), 0)) - case "c": - entry.Commit = &c - case "k": - entry.ProviderPriority = ptr(toInt(c)) - case "D": - entry.Dependencies = strings.Split(c, " ") - case "p": - entry.Dependencies = strings.Split(c, " ") - case "i": - entry.Dependencies = strings.Split(c, " ") - } - } - return entry -} diff --git a/parser/parser.go b/parser/parser.go new file mode 100644 index 0000000..8996b8c --- /dev/null +++ b/parser/parser.go @@ -0,0 +1,88 @@ +package parser + +import ( + "strconv" + "strings" + "time" +) + +type ( + // https://wiki.alpinelinux.org/wiki/Apk_spec + Entry struct { + Checksum string // C + Version string // V + Name string // P + Architecture *string // A + PackageSize int // S + InstalledSize int // I + Description string // T + Url string // U + License string // L + Origin *string // o + Maintainer *string // m + BuildTime *time.Time // t + Commit *string // c + ProviderPriority *int // k + Dependencies []string // D + Provides []string // p + InstallIf []string // i + } +) + +func ptr[T any](v T) *T { + return &v +} + +func split(line string) (string, string) { + parts := strings.SplitN(line, ":", 2) + return parts[0], parts[1] +} + +func toInt(v string) int { + i, _ := strconv.Atoi(v) + return i +} + +func Parse(lines []string) *Entry { + entry := &Entry{} + for _, line := range lines { + r, c := split(line) + switch r { + case "C": + entry.Checksum = c + case "V": + entry.Version = c + case "P": + entry.Name = c + case "A": + entry.Architecture = &c + case "S": + entry.PackageSize = toInt(c) + case "I": + entry.InstalledSize = toInt(c) + case "T": + entry.Description = c + case "U": + entry.Url = c + case "L": + entry.License = c + case "o": + entry.Origin = &c + case "m": + entry.Maintainer = &c + case "t": + entry.BuildTime = ptr(time.Unix(int64(toInt(c)), 0)) + case "c": + entry.Commit = &c + case "k": + entry.ProviderPriority = ptr(toInt(c)) + case "D": + entry.Dependencies = strings.Split(c, " ") + case "p": + entry.Dependencies = strings.Split(c, " ") + case "i": + entry.Dependencies = strings.Split(c, " ") + } + } + return entry +} diff --git a/templates/index.md.qtpl b/templates/index.md.qtpl new file mode 100644 index 0000000..879795a --- /dev/null +++ b/templates/index.md.qtpl @@ -0,0 +1,33 @@ +{% import "git.sr.ht/~gabrielgio/apkdoc/parser" %} +{% import "strings" %} + +{% code +func reduce(lines []string) string { + return strings.Join(lines, " ") +} +%} + +{% func MarkdownTemplate(entries []*parser.Entry) %} +# Apks Alpine 3.18 +{% for _, e := range entries %} +## {%s e.Name %} + +**Version**: {%s e.Version%} +**Description**: {%s e.Description%} +{% if e.Maintainer != nil %}**Maintainer**: {%s *e.Maintainer%}{% endif %} +**Checksum**:{%s e.Checksum%} +{% if e.Architecture != nil %}**Architecture**: {%s *e.Architecture%}{% endif %} +**Size**: {%d e.PackageSize%}B +**Installed size**: {%d e.InstalledSize%} +**Url**: {%s e.Url%} +**License**: {%s e.License%} +{% if e.Origin != nil %}**Origin**: {%s *e.Origin%}{% endif %} +{% if e.BuildTime != nil %}**Build time**: {%s e.BuildTime.String() %}{% endif %} +{% if e.Commit != nil %}**Commit**: {%s *e.Commit %}{% endif %} +{% if e.ProviderPriority != nil %}**Provider Priority**: {%d *e.ProviderPriority %}{% endif %} +{% if len(e.Dependencies) > 0 %}**Dependencies:**: {%s reduce(e.Dependencies) %}{% endif %} +{% if len(e.Provides) > 0 %}**Provides:**: {%s reduce(e.Provides) %}{% endif %} +{% if len(e.InstallIf) > 0 %}**Install if:**: {%s reduce(e.InstallIf) %}{% endif %} +{% endfor %} + +{% endfunc %} diff --git a/templates/index.md.qtpl.go b/templates/index.md.qtpl.go new file mode 100644 index 0000000..af3d34a --- /dev/null +++ b/templates/index.md.qtpl.go @@ -0,0 +1,215 @@ +// Code generated by qtc from "index.md.qtpl". DO NOT EDIT. +// See https://github.com/valyala/quicktemplate for details. + +//line index.md.qtpl:1 +package templates + +//line index.md.qtpl:1 +import "git.sr.ht/~gabrielgio/apkdoc/parser" + +//line index.md.qtpl:2 +import "strings" + +//line index.md.qtpl:4 +import ( + qtio422016 "io" + + qt422016 "github.com/valyala/quicktemplate" +) + +//line index.md.qtpl:4 +var ( + _ = qtio422016.Copy + _ = qt422016.AcquireByteBuffer +) + +//line index.md.qtpl:5 +func reduce(lines []string) string { + return strings.Join(lines, " ") +} + +//line index.md.qtpl:10 +func StreamMarkdownTemplate(qw422016 *qt422016.Writer, entries []*parser.Entry) { +//line index.md.qtpl:10 + qw422016.N().S(` +# Apks Alpine 3.18 +`) +//line index.md.qtpl:12 + for _, e := range entries { +//line index.md.qtpl:12 + qw422016.N().S(` +## `) +//line index.md.qtpl:13 + qw422016.E().S(e.Name) +//line index.md.qtpl:13 + qw422016.N().S(` + +**Version**: `) +//line index.md.qtpl:15 + qw422016.E().S(e.Version) +//line index.md.qtpl:15 + qw422016.N().S(` +**Description**: `) +//line index.md.qtpl:16 + qw422016.E().S(e.Description) +//line index.md.qtpl:16 + qw422016.N().S(` +`) +//line index.md.qtpl:17 + if e.Maintainer != nil { +//line index.md.qtpl:17 + qw422016.N().S(`**Maintainer**: `) +//line index.md.qtpl:17 + qw422016.E().S(*e.Maintainer) +//line index.md.qtpl:17 + } +//line index.md.qtpl:17 + qw422016.N().S(` +**Checksum**:`) +//line index.md.qtpl:18 + qw422016.E().S(e.Checksum) +//line index.md.qtpl:18 + qw422016.N().S(` +`) +//line index.md.qtpl:19 + if e.Architecture != nil { +//line index.md.qtpl:19 + qw422016.N().S(`**Architecture**: `) +//line index.md.qtpl:19 + qw422016.E().S(*e.Architecture) +//line index.md.qtpl:19 + } +//line index.md.qtpl:19 + qw422016.N().S(` +**Size**: `) +//line index.md.qtpl:20 + qw422016.N().D(e.PackageSize) +//line index.md.qtpl:20 + qw422016.N().S(`B +**Installed size**: `) +//line index.md.qtpl:21 + qw422016.N().D(e.InstalledSize) +//line index.md.qtpl:21 + qw422016.N().S(` +**Url**: `) +//line index.md.qtpl:22 + qw422016.E().S(e.Url) +//line index.md.qtpl:22 + qw422016.N().S(` +**License**: `) +//line index.md.qtpl:23 + qw422016.E().S(e.License) +//line index.md.qtpl:23 + qw422016.N().S(` +`) +//line index.md.qtpl:24 + if e.Origin != nil { +//line index.md.qtpl:24 + qw422016.N().S(`**Origin**: `) +//line index.md.qtpl:24 + qw422016.E().S(*e.Origin) +//line index.md.qtpl:24 + } +//line index.md.qtpl:24 + qw422016.N().S(` +`) +//line index.md.qtpl:25 + if e.BuildTime != nil { +//line index.md.qtpl:25 + qw422016.N().S(`**Build time**: `) +//line index.md.qtpl:25 + qw422016.E().S(e.BuildTime.String()) +//line index.md.qtpl:25 + } +//line index.md.qtpl:25 + qw422016.N().S(` +`) +//line index.md.qtpl:26 + if e.Commit != nil { +//line index.md.qtpl:26 + qw422016.N().S(`**Commit**: `) +//line index.md.qtpl:26 + qw422016.E().S(*e.Commit) +//line index.md.qtpl:26 + } +//line index.md.qtpl:26 + qw422016.N().S(` +`) +//line index.md.qtpl:27 + if e.ProviderPriority != nil { +//line index.md.qtpl:27 + qw422016.N().S(`**Provider Priority**: `) +//line index.md.qtpl:27 + qw422016.N().D(*e.ProviderPriority) +//line index.md.qtpl:27 + } +//line index.md.qtpl:27 + qw422016.N().S(` +`) +//line index.md.qtpl:28 + if len(e.Dependencies) > 0 { +//line index.md.qtpl:28 + qw422016.N().S(`**Dependencies:**: `) +//line index.md.qtpl:28 + qw422016.E().S(reduce(e.Dependencies)) +//line index.md.qtpl:28 + } +//line index.md.qtpl:28 + qw422016.N().S(` +`) +//line index.md.qtpl:29 + if len(e.Provides) > 0 { +//line index.md.qtpl:29 + qw422016.N().S(`**Provides:**: `) +//line index.md.qtpl:29 + qw422016.E().S(reduce(e.Provides)) +//line index.md.qtpl:29 + } +//line index.md.qtpl:29 + qw422016.N().S(` +`) +//line index.md.qtpl:30 + if len(e.InstallIf) > 0 { +//line index.md.qtpl:30 + qw422016.N().S(`**Install if:**: `) +//line index.md.qtpl:30 + qw422016.E().S(reduce(e.InstallIf)) +//line index.md.qtpl:30 + } +//line index.md.qtpl:30 + qw422016.N().S(` +`) +//line index.md.qtpl:31 + } +//line index.md.qtpl:31 + qw422016.N().S(` + +`) +//line index.md.qtpl:33 +} + +//line index.md.qtpl:33 +func WriteMarkdownTemplate(qq422016 qtio422016.Writer, entries []*parser.Entry) { +//line index.md.qtpl:33 + qw422016 := qt422016.AcquireWriter(qq422016) +//line index.md.qtpl:33 + StreamMarkdownTemplate(qw422016, entries) +//line index.md.qtpl:33 + qt422016.ReleaseWriter(qw422016) +//line index.md.qtpl:33 +} + +//line index.md.qtpl:33 +func MarkdownTemplate(entries []*parser.Entry) string { +//line index.md.qtpl:33 + qb422016 := qt422016.AcquireByteBuffer() +//line index.md.qtpl:33 + WriteMarkdownTemplate(qb422016, entries) +//line index.md.qtpl:33 + qs422016 := string(qb422016.B) +//line index.md.qtpl:33 + qt422016.ReleaseByteBuffer(qb422016) +//line index.md.qtpl:33 + return qs422016 +//line index.md.qtpl:33 +} -- cgit v1.2.3