pango2 template engine
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
0cf5eb4d40
commit
37cb244ffb
14 changed files with 320 additions and 165 deletions
|
@ -38,3 +38,4 @@ __DONE__
|
||||||
* about
|
* about
|
||||||
* migrate to gRPC
|
* migrate to gRPC
|
||||||
* routing, not found
|
* routing, not found
|
||||||
|
* template engine
|
||||||
|
|
34
formatter.go
34
formatter.go
|
@ -1,9 +1,43 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
|
"net/url"
|
||||||
"sort"
|
"sort"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func (file *TreeFile) CategoriesAsUrl() string {
|
||||||
|
escapedCategories := []string{}
|
||||||
|
for _, c := range file.Category {
|
||||||
|
escapedCategories = append(escapedCategories, url.QueryEscape(c))
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.Join(escapedCategories, "/")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (file *TreeFile) GmiName() string {
|
||||||
|
return strings.Replace(file.Name, ".md", ".gmi", 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tree *Tree) GetIndexFile() (*TreeFile, error) {
|
||||||
|
for _, file := range tree.RootFiles {
|
||||||
|
if file.Name == "index.md" {
|
||||||
|
return file, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, errors.New("index file not found")
|
||||||
|
}
|
||||||
|
func (tree *Tree) HasIndexFile() bool {
|
||||||
|
_, err := tree.GetIndexFile()
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func GetLastFiles(files []*TreeFile) []*TreeFile {
|
func GetLastFiles(files []*TreeFile) []*TreeFile {
|
||||||
sortingFiles := make(map[string]*TreeFile)
|
sortingFiles := make(map[string]*TreeFile)
|
||||||
for _, f := range files {
|
for _, f := range files {
|
||||||
|
|
1
go.mod
1
go.mod
|
@ -4,6 +4,7 @@ go 1.18
|
||||||
|
|
||||||
require (
|
require (
|
||||||
git.sr.ht/~adnano/go-gemini v0.2.3
|
git.sr.ht/~adnano/go-gemini v0.2.3
|
||||||
|
github.com/flosch/pongo2/v6 v6.0.0
|
||||||
google.golang.org/grpc v1.48.0
|
google.golang.org/grpc v1.48.0
|
||||||
google.golang.org/protobuf v1.28.1
|
google.golang.org/protobuf v1.28.1
|
||||||
)
|
)
|
||||||
|
|
5
go.sum
5
go.sum
|
@ -20,6 +20,8 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m
|
||||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||||
github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE=
|
github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE=
|
||||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||||
|
github.com/flosch/pongo2/v6 v6.0.0 h1:lsGru8IAzHgIAw6H2m4PCyleO58I40ow6apih0WprMU=
|
||||||
|
github.com/flosch/pongo2/v6 v6.0.0/go.mod h1:CuDpFm47R0uGGE7z13/tTlt1Y6zdxvr2RLT5LJhsHEU=
|
||||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
|
@ -47,6 +49,8 @@ github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
|
||||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||||
|
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
|
||||||
|
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||||
|
@ -126,6 +130,7 @@ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ
|
||||||
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
|
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
|
||||||
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
|
281
main.go
281
main.go
|
@ -6,13 +6,13 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"google.golang.org/grpc/credentials/insecure"
|
"google.golang.org/grpc/credentials/insecure"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.sr.ht/~adnano/go-gemini"
|
"git.sr.ht/~adnano/go-gemini"
|
||||||
"git.sr.ht/~adnano/go-gemini/certificate"
|
"git.sr.ht/~adnano/go-gemini/certificate"
|
||||||
|
"github.com/flosch/pongo2/v6"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -62,7 +62,10 @@ func main() {
|
||||||
|
|
||||||
func processFavicon(_ context.Context, w gemini.ResponseWriter, _ *gemini.Request) {
|
func processFavicon(_ context.Context, w gemini.ResponseWriter, _ *gemini.Request) {
|
||||||
w.SetMediaType("text/plain")
|
w.SetMediaType("text/plain")
|
||||||
w.Write([]byte("\U0001F31B"))
|
_, err := w.Write([]byte("\U0001F31B"))
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(gemini.StatusNotFound, "Out of space")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func process(_ context.Context, w gemini.ResponseWriter, r *gemini.Request) {
|
func process(_ context.Context, w gemini.ResponseWriter, r *gemini.Request) {
|
||||||
|
@ -93,12 +96,175 @@ func process(_ context.Context, w gemini.ResponseWriter, r *gemini.Request) {
|
||||||
renderSearch(lang, w, r, client)
|
renderSearch(lang, w, r, client)
|
||||||
case regexp.MustCompile(`^/(sgs|en)/f/?$`).MatchString(r.URL.Path):
|
case regexp.MustCompile(`^/(sgs|en)/f/?$`).MatchString(r.URL.Path):
|
||||||
renderAllFiles(lang, w, client)
|
renderAllFiles(lang, w, client)
|
||||||
|
case regexp.MustCompile(`^/(sgs|en)/f/([\p{L}\d_+.]+/)+[\d\w]+/[\w_]+.gmi$`).MatchString(r.URL.Path):
|
||||||
|
renderFile(lang, w, r, client)
|
||||||
|
case regexp.MustCompile(`^/(sgs|en)/f/[\p{L}\d_+.]+(/[\p{L}\d_+.]+)*/?$`).MatchString(r.URL.Path):
|
||||||
|
renderCategory(lang, w, r, client)
|
||||||
default:
|
default:
|
||||||
w.WriteHeader(gemini.StatusNotFound, "Out of space")
|
w.WriteHeader(gemini.StatusNotFound, "Out of space")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func renderIndex(lang string, w gemini.ResponseWriter, client TreeManagerClient) {
|
||||||
|
langFilter := TreeRequest_Filter{Key: "lang", Value: lang}
|
||||||
|
filters := []*TreeRequest_Filter{&langFilter}
|
||||||
|
|
||||||
|
path := ""
|
||||||
|
tr := TreeRequest{Path: &path, Filter: filters}
|
||||||
|
|
||||||
|
tree, err := client.GetSummery(context.Background(), &tr)
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(gemini.StatusTemporaryFailure, "Internal server error")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
w.SetMediaType("text/gemini")
|
||||||
|
tpl := pongo2.Must(pongo2.FromFile(fmt.Sprintf("templates/%s/index.gmi", lang)))
|
||||||
|
page, err := tpl.Execute(pongo2.Context{"tree": tree, "lang": lang, "lastFiles": GetLastFiles(tree.Files)})
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("template failed: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = w.Write([]byte(page))
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(gemini.StatusTemporaryFailure, "Internal server error")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func renderAbout(lang string, w gemini.ResponseWriter) {
|
||||||
|
w.SetMediaType("text/gemini")
|
||||||
|
tpl := pongo2.Must(pongo2.FromFile(fmt.Sprintf("templates/%s/about.gmi", lang)))
|
||||||
|
page, err := tpl.Execute(pongo2.Context{})
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("template failed: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = w.Write([]byte(page))
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(gemini.StatusTemporaryFailure, "Internal server error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func renderSearch(lang string, w gemini.ResponseWriter, r *gemini.Request, client TreeManagerClient) {
|
||||||
|
q, err := gemini.QueryUnescape(r.URL.RawQuery)
|
||||||
|
if err != nil || q == "" {
|
||||||
|
searchStr := "Input searching tag, created date or word in description"
|
||||||
|
if lang == "sgs" {
|
||||||
|
searchStr = "Ivesk ėiškuoma žīma, sokūrėma data arba žuodi ėš aprašīma"
|
||||||
|
}
|
||||||
|
w.WriteHeader(gemini.StatusInput, searchStr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
descFilter := TreeRequest_Filter{Key: "description", Value: q}
|
||||||
|
createdFilter := TreeRequest_Filter{Key: "created", Value: q}
|
||||||
|
tagFilter := TreeRequest_Filter{Key: "tag", Value: q}
|
||||||
|
filters := []*TreeRequest_Filter{&descFilter, &createdFilter, &tagFilter}
|
||||||
|
|
||||||
|
path := ""
|
||||||
|
tr := TreeRequest{Path: &path, Filter: filters}
|
||||||
|
|
||||||
|
tree, err := client.GetSummery(context.Background(), &tr)
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(gemini.StatusTemporaryFailure, "Internal server error")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
w.SetMediaType("text/gemini")
|
||||||
|
tpl := pongo2.Must(pongo2.FromFile("templates/search.gmi"))
|
||||||
|
page, err := tpl.Execute(pongo2.Context{"lang": lang, "tree": tree, "q": q})
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("template failed: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = w.Write([]byte(page))
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(gemini.StatusTemporaryFailure, "Internal server error")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func renderCategory(lang string, w gemini.ResponseWriter, r *gemini.Request, client TreeManagerClient) {
|
||||||
|
urlParts := strings.Split(strings.Trim(r.URL.Path, "/"), "/")
|
||||||
|
path := "/" + strings.Join(urlParts[2:], "/")
|
||||||
|
|
||||||
|
tr := TreeRequest{Path: &path, Filter: []*TreeRequest_Filter{}}
|
||||||
|
|
||||||
|
tree, err := client.GetSummery(context.Background(), &tr)
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(gemini.StatusTemporaryFailure, "Internal server error")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
indexFile, err := tree.GetIndexFile()
|
||||||
|
var file *FileContent
|
||||||
|
if err == nil {
|
||||||
|
fr := FileRequest{Id: indexFile.Id}
|
||||||
|
file, err = client.GetFile(context.Background(), &fr)
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(gemini.StatusTemporaryFailure, "Internal server error")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
w.SetMediaType("text/gemini")
|
||||||
|
tpl := pongo2.Must(pongo2.FromFile("templates/category.gmi"))
|
||||||
|
fmt.Println(file, &file)
|
||||||
|
page, err := tpl.Execute(pongo2.Context{"lang": lang, "tree": tree, "path": path, "indexFile": file})
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("template failed: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = w.Write([]byte(page))
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(gemini.StatusTemporaryFailure, "Internal server error")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func renderFile(lang string, w gemini.ResponseWriter, r *gemini.Request, client TreeManagerClient) {
|
||||||
|
urlParts := strings.Split(r.URL.Path, "/")
|
||||||
|
id := urlParts[len(urlParts)-2]
|
||||||
|
|
||||||
|
fr := FileRequest{Id: id}
|
||||||
|
file, err := client.GetFile(context.Background(), &fr)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("client.GetSummery failed: %v", err)
|
||||||
|
w.WriteHeader(gemini.StatusTemporaryFailure, "Internal server error")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
category := ""
|
||||||
|
for i, cat := range file.File.Category {
|
||||||
|
category = category + fmt.Sprintf("=> /%s/f/%s .%s└─ %s\n",
|
||||||
|
lang,
|
||||||
|
strings.Join(file.File.Category[:i+1], "/"),
|
||||||
|
strings.Repeat(" ", i),
|
||||||
|
cat,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
content := fmt.Sprintf(
|
||||||
|
"# %s\n\n"+
|
||||||
|
"%s\n\n"+
|
||||||
|
"%s\n%s\n\n"+
|
||||||
|
"%s\n\n[ %s ]",
|
||||||
|
file.File.Description,
|
||||||
|
file.Content,
|
||||||
|
file.File.Created,
|
||||||
|
file.File.Copyright,
|
||||||
|
category,
|
||||||
|
strings.Join(file.File.Tags, " "),
|
||||||
|
)
|
||||||
|
|
||||||
|
w.Write([]byte(content))
|
||||||
|
}
|
||||||
|
|
||||||
func renderAllFiles(lang string, w gemini.ResponseWriter, client TreeManagerClient) {
|
func renderAllFiles(lang string, w gemini.ResponseWriter, client TreeManagerClient) {
|
||||||
langFilter := TreeRequest_Filter{Key: "lang", Value: lang}
|
langFilter := TreeRequest_Filter{Key: "lang", Value: lang}
|
||||||
filters := []*TreeRequest_Filter{&langFilter}
|
filters := []*TreeRequest_Filter{&langFilter}
|
||||||
|
@ -121,15 +287,7 @@ func renderAllFiles(lang string, w gemini.ResponseWriter, client TreeManagerClie
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, f := range tree.Files {
|
for _, f := range tree.Files {
|
||||||
content = content + fmt.Sprintf(
|
content = appendFileLink(lang, content, f)
|
||||||
"=> /%s/f/%s/%s/%s %s (%s)\n",
|
|
||||||
lang,
|
|
||||||
strings.Join(f.Category, "/"),
|
|
||||||
f.Id,
|
|
||||||
strings.Replace(f.Name, ".md", ".gmi", 1),
|
|
||||||
f.Description,
|
|
||||||
f.Created,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if lang == "sgs" {
|
if lang == "sgs" {
|
||||||
|
@ -141,98 +299,15 @@ func renderAllFiles(lang string, w gemini.ResponseWriter, client TreeManagerClie
|
||||||
w.Write([]byte(content))
|
w.Write([]byte(content))
|
||||||
}
|
}
|
||||||
|
|
||||||
func renderSearch(lang string, w gemini.ResponseWriter, r *gemini.Request, client TreeManagerClient) {
|
func appendFileLink(lang string, content string, f *TreeFile) string {
|
||||||
q, err := gemini.QueryUnescape(r.URL.RawQuery)
|
content = content + fmt.Sprintf(
|
||||||
if err != nil || q == "" {
|
|
||||||
searchStr := "Input searching tag, created date or word in description"
|
|
||||||
if lang == "sgs" {
|
|
||||||
searchStr = "Ivesk ėiškuoma žīma, sokūrėma data arba žuodi ėš aprašīma"
|
|
||||||
}
|
|
||||||
w.WriteHeader(gemini.StatusInput, searchStr)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
langFilter := TreeRequest_Filter{Key: "lang", Value: lang}
|
|
||||||
descFilter := TreeRequest_Filter{Key: "description", Value: lang}
|
|
||||||
createdFilter := TreeRequest_Filter{Key: "created", Value: lang}
|
|
||||||
tagFilter := TreeRequest_Filter{Key: "tag", Value: lang}
|
|
||||||
filters := []*TreeRequest_Filter{&langFilter, &descFilter, &createdFilter, &tagFilter}
|
|
||||||
|
|
||||||
path := ""
|
|
||||||
tr := TreeRequest{Path: &path, Filter: filters}
|
|
||||||
|
|
||||||
tree, err := client.GetSummery(context.Background(), &tr)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("client.GetSummery failed: %v", err)
|
|
||||||
w.WriteHeader(gemini.StatusTemporaryFailure, "Internal server error")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
fmt.Println(tree)
|
|
||||||
w.Write([]byte("Nieka narada dā\n" +
|
|
||||||
"=> / ← back"))
|
|
||||||
}
|
|
||||||
|
|
||||||
func renderAbout(lang string, w gemini.ResponseWriter) {
|
|
||||||
w.SetMediaType("text/gemini")
|
|
||||||
content, err := os.ReadFile(fmt.Sprintf("templates/%s/about.gmi", lang))
|
|
||||||
if err != nil {
|
|
||||||
w.WriteHeader(gemini.StatusTemporaryFailure, "Internal server error")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = w.Write(content)
|
|
||||||
if err != nil {
|
|
||||||
w.WriteHeader(gemini.StatusTemporaryFailure, "Internal server error")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func renderIndex(lang string, w gemini.ResponseWriter, client TreeManagerClient) {
|
|
||||||
w.SetMediaType("text/gemini")
|
|
||||||
content, err := os.ReadFile(fmt.Sprintf("templates/%s/index.gmi", lang))
|
|
||||||
if err != nil {
|
|
||||||
w.WriteHeader(gemini.StatusTemporaryFailure, "Internal server error")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
page := string(content)
|
|
||||||
|
|
||||||
langFilter := TreeRequest_Filter{Key: "lang", Value: lang}
|
|
||||||
filters := []*TreeRequest_Filter{&langFilter}
|
|
||||||
|
|
||||||
path := ""
|
|
||||||
tr := TreeRequest{Path: &path, Filter: filters}
|
|
||||||
|
|
||||||
tree, err := client.GetSummery(context.Background(), &tr)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("client.GetSummery failed: %v", err)
|
|
||||||
w.WriteHeader(gemini.StatusTemporaryFailure, "Internal server error")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
categories := ""
|
|
||||||
for c, count := range tree.Categories {
|
|
||||||
categories = categories + fmt.Sprintf("=> /%s/f/%s %s (%d)\n", lang, c, c, count)
|
|
||||||
}
|
|
||||||
page = strings.Replace(page, "{{categories}}", categories, 1)
|
|
||||||
|
|
||||||
tags := ""
|
|
||||||
for t, count := range tree.Tags {
|
|
||||||
tags = tags + fmt.Sprintf("=> /%s/t/%s %s (%d)\n", lang, t, t, count)
|
|
||||||
}
|
|
||||||
page = strings.Replace(page, "{{tags}}", tags, 1)
|
|
||||||
|
|
||||||
lastFiles := ""
|
|
||||||
for _, f := range GetLastFiles(tree.Files) {
|
|
||||||
lastFiles = lastFiles + fmt.Sprintf(
|
|
||||||
"=> /%s/f/%s/%s/%s %s (%s)\n",
|
"=> /%s/f/%s/%s/%s %s (%s)\n",
|
||||||
lang, strings.Join(f.Category, "/"), f.Id, strings.Replace(f.Name, ".md", ".gmi", 1), f.Description, f.Created,
|
lang,
|
||||||
|
strings.Join(f.Category, "/"),
|
||||||
|
f.Id,
|
||||||
|
strings.Replace(f.Name, ".md", ".gmi", 1),
|
||||||
|
f.Description,
|
||||||
|
f.Created,
|
||||||
)
|
)
|
||||||
}
|
return content
|
||||||
page = strings.Replace(page, "{{last_posts}}", lastFiles, 1)
|
|
||||||
|
|
||||||
_, err = w.Write([]byte(page))
|
|
||||||
if err != nil {
|
|
||||||
w.WriteHeader(gemini.StatusTemporaryFailure, "Internal server error")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
10
templates/category.gmi
Normal file
10
templates/category.gmi
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
{% import "macros.tpl" category_url, text_url %}
|
||||||
|
# Arna alkierios :: {{ path }}
|
||||||
|
|
||||||
|
{% if indexFile %}{{ indexFile.Content }}{% endif %}
|
||||||
|
|
||||||
|
{% for file in tree.RootFiles %}{{ text_url(lang, file) }} {% endfor %}
|
||||||
|
{% if tree.Categories %}### {% if lang == "sgs" %}Kateguorėjės{% else %}Categories{% endif %}
|
||||||
|
{% for cat, count in tree.Categories %}{{ category_url(lang, cat, cat, count) }}
|
||||||
|
{% endfor %} {% endif %}
|
||||||
|
=> {% if lang == "sgs" %}/sgs 🏠 nomėi{% else %}/en 🏠 home{% endif %}
|
|
@ -27,7 +27,7 @@ Articles I wrote simply in files and put them in my self-hosted cloud by created
|
||||||
|
|
||||||
From this service it is served to gemini service what is written in Go, too, or to http service (backend on Go, frontend on Vue.js). For communications I use gRPC.
|
From this service it is served to gemini service what is written in Go, too, or to http service (backend on Go, frontend on Vue.js). For communications I use gRPC.
|
||||||
|
|
||||||
=> /en/f/gemini/arns-lt more...
|
=> /en/f/gemini/arns_lt more...
|
||||||
=> https://g.arns.lt/zordsdavini/zord-tree zord-tree library to build tree from files
|
=> https://g.arns.lt/zordsdavini/zord-tree zord-tree library to build tree from files
|
||||||
=> https://g.arns.lt/zordsdavini/arns-lt-tree-push-service service written on top of zord-tree to serve files
|
=> https://g.arns.lt/zordsdavini/arns-lt-tree-push-service service written on top of zord-tree to serve files
|
||||||
=> https://g.arns.lt/zordsdavini/arns-lt-gemini gemini service
|
=> https://g.arns.lt/zordsdavini/arns-lt-gemini gemini service
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
{% import "../macros.tpl" category_url, tag_url, text_url %}
|
||||||
# Arna alkierios
|
# Arna alkierios
|
||||||
|
|
||||||
Welcome to my capsule in Gemini space.
|
Welcome to my capsule in Gemini space.
|
||||||
|
@ -12,16 +13,16 @@ Main themes are spreaded by categories. Each file may have tags what can filter
|
||||||
=> /en/s search
|
=> /en/s search
|
||||||
=> /en/a about
|
=> /en/a about
|
||||||
|
|
||||||
### Categories
|
{% if tree.Categories %}### Categories
|
||||||
|
{% for cat, count in tree.Categories %}
|
||||||
|
{{ category_url(lang, cat, cat, count) }} {% endfor %} {% endif %}
|
||||||
|
|
||||||
{{categories}}
|
{% if tree.Tags %}### Tags
|
||||||
|
{% for tag, count in tree.Tags %}
|
||||||
|
{{ tag_url(lang, tag, count) }} {% endfor %} {% endif %}
|
||||||
|
|
||||||
### Tags
|
{% if lastFiles %}### Last texts
|
||||||
|
{% for file in lastFiles %}
|
||||||
{{tags}}
|
{{ text_url(lang, file) }} {% endfor %} {% endif %}
|
||||||
|
|
||||||
### Last posts
|
|
||||||
|
|
||||||
{{last_posts}}
|
|
||||||
|
|
||||||
=> /en/f all texts
|
=> /en/f all texts
|
||||||
|
|
5
templates/macros.tpl
Normal file
5
templates/macros.tpl
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
{% macro category_url(lang, path, category, count) export %}=> /{{ lang }}/f/{{ path }} {{ category }} ({{ count }}) {% endmacro %}
|
||||||
|
|
||||||
|
{% macro tag_url(lang, tag, count) export %}=> /{{ lang }}/t/{{ tag }} {{ tag }} ({{ count }}) {% endmacro %}
|
||||||
|
|
||||||
|
{% macro text_url(lang, file) export %}=> /{{ lang }}/f/{{ file.CategoriesAsUrl() }}/{{ file.Id }}/{{ file.GmiName() }} {{ file.Description }} ({{ file.Created }}) {% endmacro %}
|
9
templates/search.gmi
Normal file
9
templates/search.gmi
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
{% import "macros.tpl" text_url %}
|
||||||
|
# Arna alkierios :: {% if lang == "sgs" %}Paėiška{% else %}Search{% endif %}
|
||||||
|
|
||||||
|
{% if lang == "sgs" %}Ėiškuota vagol{% else %}Searched by{% endif %}: {{ q }}
|
||||||
|
{% if tree.Files|length == 0 %}{% if lang == "sgs" %}Nieka narada{% else %}Nothing found{% endif %}...{% else %}
|
||||||
|
{% for file in tree.Files %}
|
||||||
|
{{ text_url(lang, file) }} {% endfor %} {% endif %}
|
||||||
|
|
||||||
|
=> {% if lang == "sgs" %}/sgs ← grīžtė{% else %}/en ← back{% endif %}
|
|
@ -27,7 +27,7 @@ Tekstus rašau i paprastiausius failiokus ėr anus talpėno sava „cloud'ė“
|
||||||
|
|
||||||
Jau ėš makliavuonės servėsa pajemo i gemini servėsa, katras parašīts ėrgė so Go, arba i http servėsa (backend's ont Go REST, frontend's ont Vue.js). Ruodā nauduojo gRPC pruotuokuola.
|
Jau ėš makliavuonės servėsa pajemo i gemini servėsa, katras parašīts ėrgė so Go, arba i http servėsa (backend's ont Go REST, frontend's ont Vue.js). Ruodā nauduojo gRPC pruotuokuola.
|
||||||
|
|
||||||
=> /en/f/gemini/arns-lt platiau (onglėškā)
|
=> /en/f/gemini/arns_lt platiau (onglėškā)
|
||||||
=> https://g.arns.lt/zordsdavini/zord-tree zord-tree bėbliuoteka sokortė miedi ėš failu
|
=> https://g.arns.lt/zordsdavini/zord-tree zord-tree bėbliuoteka sokortė miedi ėš failu
|
||||||
=> https://g.arns.lt/zordsdavini/arns-lt-tree-push-service servėsos ont zord-tree somakliavuotė failus ėr anus padoutė tuoliau
|
=> https://g.arns.lt/zordsdavini/arns-lt-tree-push-service servėsos ont zord-tree somakliavuotė failus ėr anus padoutė tuoliau
|
||||||
=> https://g.arns.lt/zordsdavini/arns-lt-gemini gemini servėsos
|
=> https://g.arns.lt/zordsdavini/arns-lt-gemini gemini servėsos
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
{% import "../macros.tpl" category_url, tag_url, text_url %}
|
||||||
# Arna alkierios
|
# Arna alkierios
|
||||||
|
|
||||||
Sveikė atvīkėn i mona kapsolė Gemini ertie.
|
Sveikė atvīkėn i mona kapsolė Gemini ertie.
|
||||||
|
@ -12,16 +13,16 @@ Pagrindėnės temas paskėrstītas par kateguorėjės. Kuožnos fails gal turie
|
||||||
=> /sgs/s ėiškuok
|
=> /sgs/s ėiškuok
|
||||||
=> /sgs/a aple
|
=> /sgs/a aple
|
||||||
|
|
||||||
### Kateguorėjės
|
{% if tree.Categories %}### Kateguorėjės
|
||||||
|
{% for cat, count in tree.Categories %}
|
||||||
|
{{ category_url(lang, cat, cat, count) }} {% endfor %} {% endif %}
|
||||||
|
|
||||||
{{categories}}
|
{% if tree.Tags %}### Žīmas
|
||||||
|
{% for tag, count in tree.Tags %}
|
||||||
|
{{ tag_url(lang, tag, count) }} {% endfor %} {% endif %}
|
||||||
|
|
||||||
### Žīmas
|
{% if lastFiles %}### Paskotėnē īrašā
|
||||||
|
{% for file in lastFiles %}
|
||||||
{{tags}}
|
{{ text_url(lang, file) }} {% endfor %} {% endif %}
|
||||||
|
|
||||||
### Paskotėnē īrašā
|
|
||||||
|
|
||||||
{{last_posts}}
|
|
||||||
|
|
||||||
=> /sgs/f vėsė straipsnē
|
=> /sgs/f vėsė straipsnē
|
||||||
|
|
92
tree.pb.go
92
tree.pb.go
|
@ -231,6 +231,7 @@ type Tree struct {
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
Files []*TreeFile `protobuf:"bytes,1,rep,name=files,proto3" json:"files,omitempty"`
|
Files []*TreeFile `protobuf:"bytes,1,rep,name=files,proto3" json:"files,omitempty"`
|
||||||
|
RootFiles []*TreeFile `protobuf:"bytes,4,rep,name=rootFiles,proto3" json:"rootFiles,omitempty"`
|
||||||
Tags map[string]int32 `protobuf:"bytes,2,rep,name=tags,proto3" json:"tags,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`
|
Tags map[string]int32 `protobuf:"bytes,2,rep,name=tags,proto3" json:"tags,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`
|
||||||
Categories map[string]int32 `protobuf:"bytes,3,rep,name=categories,proto3" json:"categories,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`
|
Categories map[string]int32 `protobuf:"bytes,3,rep,name=categories,proto3" json:"categories,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`
|
||||||
}
|
}
|
||||||
|
@ -274,6 +275,13 @@ func (x *Tree) GetFiles() []*TreeFile {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *Tree) GetRootFiles() []*TreeFile {
|
||||||
|
if x != nil {
|
||||||
|
return x.RootFiles
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (x *Tree) GetTags() map[string]int32 {
|
func (x *Tree) GetTags() map[string]int32 {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.Tags
|
return x.Tags
|
||||||
|
@ -426,36 +434,39 @@ var file_tree_proto_rawDesc = []byte{
|
||||||
0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73,
|
0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73,
|
||||||
0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x12, 0x18, 0x0a, 0x07,
|
0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x12, 0x18, 0x0a, 0x07,
|
||||||
0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63,
|
0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63,
|
||||||
0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x22, 0x8a, 0x02, 0x0a, 0x04, 0x54, 0x72, 0x65, 0x65, 0x12,
|
0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x22, 0xb8, 0x02, 0x0a, 0x04, 0x54, 0x72, 0x65, 0x65, 0x12,
|
||||||
0x24, 0x0a, 0x05, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e,
|
0x24, 0x0a, 0x05, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e,
|
||||||
0x2e, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x05,
|
0x2e, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x05,
|
||||||
0x66, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x28, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x02, 0x20,
|
0x66, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x2c, 0x0a, 0x09, 0x72, 0x6f, 0x6f, 0x74, 0x46, 0x69, 0x6c,
|
||||||
0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x2e,
|
0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x6d, 0x61, 0x69, 0x6e, 0x2e,
|
||||||
0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x12,
|
0x54, 0x72, 0x65, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x09, 0x72, 0x6f, 0x6f, 0x74, 0x46, 0x69,
|
||||||
0x3a, 0x0a, 0x0a, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x18, 0x03, 0x20,
|
0x6c, 0x65, 0x73, 0x12, 0x28, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28,
|
||||||
0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x2e,
|
0x0b, 0x32, 0x14, 0x2e, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x2e, 0x54, 0x61,
|
||||||
0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52,
|
0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x12, 0x3a, 0x0a,
|
||||||
0x0a, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x1a, 0x37, 0x0a, 0x09, 0x54,
|
0x0a, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28,
|
||||||
0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18,
|
0x0b, 0x32, 0x1a, 0x2e, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x2e, 0x43, 0x61,
|
||||||
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61,
|
0x74, 0x65, 0x67, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x63,
|
||||||
0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
|
0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x1a, 0x37, 0x0a, 0x09, 0x54, 0x61, 0x67,
|
||||||
0x3a, 0x02, 0x38, 0x01, 0x1a, 0x3d, 0x0a, 0x0f, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x69,
|
0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20,
|
||||||
0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01,
|
0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75,
|
||||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c,
|
0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02,
|
||||||
0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a,
|
0x38, 0x01, 0x1a, 0x3d, 0x0a, 0x0f, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x69, 0x65, 0x73,
|
||||||
0x02, 0x38, 0x01, 0x22, 0x4b, 0x0a, 0x0b, 0x46, 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65,
|
0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01,
|
||||||
0x6e, 0x74, 0x12, 0x22, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
|
0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
|
||||||
0x32, 0x0e, 0x2e, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x46, 0x69, 0x6c, 0x65,
|
0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38,
|
||||||
0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e,
|
0x01, 0x22, 0x4b, 0x0a, 0x0b, 0x46, 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74,
|
||||||
0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74,
|
0x12, 0x22, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e,
|
||||||
0x32, 0x6f, 0x0a, 0x0b, 0x54, 0x72, 0x65, 0x65, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x12,
|
0x2e, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x04,
|
||||||
0x2d, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x53, 0x75, 0x6d, 0x6d, 0x65, 0x72, 0x79, 0x12, 0x11, 0x2e,
|
0x66, 0x69, 0x6c, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18,
|
||||||
0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x32, 0x6f,
|
||||||
0x1a, 0x0a, 0x2e, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x22, 0x00, 0x12, 0x31,
|
0x0a, 0x0b, 0x54, 0x72, 0x65, 0x65, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x12, 0x2d, 0x0a,
|
||||||
0x0a, 0x07, 0x47, 0x65, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x11, 0x2e, 0x6d, 0x61, 0x69, 0x6e,
|
0x0a, 0x47, 0x65, 0x74, 0x53, 0x75, 0x6d, 0x6d, 0x65, 0x72, 0x79, 0x12, 0x11, 0x2e, 0x6d, 0x61,
|
||||||
0x2e, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x6d,
|
0x69, 0x6e, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0a,
|
||||||
0x61, 0x69, 0x6e, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x22,
|
0x2e, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x22, 0x00, 0x12, 0x31, 0x0a, 0x07,
|
||||||
0x00, 0x42, 0x03, 0x5a, 0x01, 0x2e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
0x47, 0x65, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x11, 0x2e, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x46,
|
||||||
|
0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x6d, 0x61, 0x69,
|
||||||
|
0x6e, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x22, 0x00, 0x42,
|
||||||
|
0x03, 0x5a, 0x01, 0x2e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -484,18 +495,19 @@ var file_tree_proto_goTypes = []interface{}{
|
||||||
var file_tree_proto_depIdxs = []int32{
|
var file_tree_proto_depIdxs = []int32{
|
||||||
5, // 0: main.TreeRequest.filter:type_name -> main.TreeRequest.Filter
|
5, // 0: main.TreeRequest.filter:type_name -> main.TreeRequest.Filter
|
||||||
2, // 1: main.Tree.files:type_name -> main.TreeFile
|
2, // 1: main.Tree.files:type_name -> main.TreeFile
|
||||||
6, // 2: main.Tree.tags:type_name -> main.Tree.TagsEntry
|
2, // 2: main.Tree.rootFiles:type_name -> main.TreeFile
|
||||||
7, // 3: main.Tree.categories:type_name -> main.Tree.CategoriesEntry
|
6, // 3: main.Tree.tags:type_name -> main.Tree.TagsEntry
|
||||||
2, // 4: main.FileContent.file:type_name -> main.TreeFile
|
7, // 4: main.Tree.categories:type_name -> main.Tree.CategoriesEntry
|
||||||
1, // 5: main.TreeManager.GetSummery:input_type -> main.TreeRequest
|
2, // 5: main.FileContent.file:type_name -> main.TreeFile
|
||||||
0, // 6: main.TreeManager.GetFile:input_type -> main.FileRequest
|
1, // 6: main.TreeManager.GetSummery:input_type -> main.TreeRequest
|
||||||
3, // 7: main.TreeManager.GetSummery:output_type -> main.Tree
|
0, // 7: main.TreeManager.GetFile:input_type -> main.FileRequest
|
||||||
4, // 8: main.TreeManager.GetFile:output_type -> main.FileContent
|
3, // 8: main.TreeManager.GetSummery:output_type -> main.Tree
|
||||||
7, // [7:9] is the sub-list for method output_type
|
4, // 9: main.TreeManager.GetFile:output_type -> main.FileContent
|
||||||
5, // [5:7] is the sub-list for method input_type
|
8, // [8:10] is the sub-list for method output_type
|
||||||
5, // [5:5] is the sub-list for extension type_name
|
6, // [6:8] is the sub-list for method input_type
|
||||||
5, // [5:5] is the sub-list for extension extendee
|
6, // [6:6] is the sub-list for extension type_name
|
||||||
0, // [0:5] is the sub-list for field type_name
|
6, // [6:6] is the sub-list for extension extendee
|
||||||
|
0, // [0:6] is the sub-list for field type_name
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { file_tree_proto_init() }
|
func init() { file_tree_proto_init() }
|
||||||
|
|
|
@ -39,6 +39,7 @@ message TreeFile {
|
||||||
|
|
||||||
message Tree {
|
message Tree {
|
||||||
repeated TreeFile files = 1;
|
repeated TreeFile files = 1;
|
||||||
|
repeated TreeFile rootFiles = 4;
|
||||||
map<string, int32> tags = 2;
|
map<string, int32> tags = 2;
|
||||||
map<string, int32> categories = 3;
|
map<string, int32> categories = 3;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue