This commit is contained in:
parent
37cb244ffb
commit
c946b9daba
10 changed files with 126 additions and 89 deletions
26
README.md
26
README.md
|
@ -5,36 +5,16 @@
|
||||||
My capsule in Gemini space. Built with zord-tree support
|
My capsule in Gemini space. Built with zord-tree support
|
||||||
|
|
||||||
|
|
||||||
## URL plan
|
|
||||||
|
|
||||||
* / - redirect to /sgs
|
|
||||||
* /sgs or /en - index template by language. Links to other language, about, search, root categories, all tags, last 10 post, link to all posts
|
|
||||||
* /[sgs|en]/a - about page
|
|
||||||
* /[sgs|en]/s - search
|
|
||||||
* /[sgs|en]/f/<category/path> - display files, subcategories, subtags. If exists index.gmi - display its text
|
|
||||||
* /[sgs|en]/f/<category/path>/<id>/<name.gmi> - display category path as:
|
|
||||||
```
|
|
||||||
=> /sgs/f/c1 c1
|
|
||||||
=> /sgs/f/c1/c2 └─ c2
|
|
||||||
=> /sgs/f/c1/c2/c3 , └─ c3
|
|
||||||
---
|
|
||||||
> c1
|
|
||||||
> └─ c2
|
|
||||||
> , └─ c3
|
|
||||||
```
|
|
||||||
display tags, date, copyright
|
|
||||||
|
|
||||||
|
|
||||||
## TODO
|
## TODO
|
||||||
|
|
||||||
* add category view
|
|
||||||
* add tag view
|
|
||||||
* add file view
|
|
||||||
* add image or other file not `gmi` download
|
* add image or other file not `gmi` download
|
||||||
* feed
|
* feed
|
||||||
* security
|
* security
|
||||||
* citata from some file
|
* citata from some file
|
||||||
__DONE__
|
__DONE__
|
||||||
|
* add category view
|
||||||
|
* add tag view
|
||||||
|
* add file view
|
||||||
* about
|
* about
|
||||||
* migrate to gRPC
|
* migrate to gRPC
|
||||||
* routing, not found
|
* routing, not found
|
||||||
|
|
12
formatter.go
12
formatter.go
|
@ -20,6 +20,10 @@ func (file *TreeFile) GmiName() string {
|
||||||
return strings.Replace(file.Name, ".md", ".gmi", 1)
|
return strings.Replace(file.Name, ".md", ".gmi", 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (file *TreeFile) CategoryPath() string {
|
||||||
|
return "/" + strings.Join(file.Category, "/")
|
||||||
|
}
|
||||||
|
|
||||||
func (tree *Tree) GetIndexFile() (*TreeFile, error) {
|
func (tree *Tree) GetIndexFile() (*TreeFile, error) {
|
||||||
for _, file := range tree.RootFiles {
|
for _, file := range tree.RootFiles {
|
||||||
if file.Name == "index.md" {
|
if file.Name == "index.md" {
|
||||||
|
@ -29,14 +33,6 @@ func (tree *Tree) GetIndexFile() (*TreeFile, error) {
|
||||||
|
|
||||||
return nil, errors.New("index file not found")
|
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)
|
||||||
|
|
95
main.go
95
main.go
|
@ -100,6 +100,9 @@ func process(_ context.Context, w gemini.ResponseWriter, r *gemini.Request) {
|
||||||
renderFile(lang, w, r, client)
|
renderFile(lang, w, r, client)
|
||||||
case regexp.MustCompile(`^/(sgs|en)/f/[\p{L}\d_+.]+(/[\p{L}\d_+.]+)*/?$`).MatchString(r.URL.Path):
|
case regexp.MustCompile(`^/(sgs|en)/f/[\p{L}\d_+.]+(/[\p{L}\d_+.]+)*/?$`).MatchString(r.URL.Path):
|
||||||
renderCategory(lang, w, r, client)
|
renderCategory(lang, w, r, client)
|
||||||
|
case regexp.MustCompile(`^/(sgs|en)/t/[\p{L}\d_+.]+/?$`).MatchString(r.URL.Path):
|
||||||
|
renderTag(lang, w, r, client)
|
||||||
|
// case abruozdelee
|
||||||
default:
|
default:
|
||||||
w.WriteHeader(gemini.StatusNotFound, "Out of space")
|
w.WriteHeader(gemini.StatusNotFound, "Out of space")
|
||||||
}
|
}
|
||||||
|
@ -214,7 +217,6 @@ func renderCategory(lang string, w gemini.ResponseWriter, r *gemini.Request, cli
|
||||||
|
|
||||||
w.SetMediaType("text/gemini")
|
w.SetMediaType("text/gemini")
|
||||||
tpl := pongo2.Must(pongo2.FromFile("templates/category.gmi"))
|
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})
|
page, err := tpl.Execute(pongo2.Context{"lang": lang, "tree": tree, "path": path, "indexFile": file})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("template failed: %v", err)
|
log.Fatalf("template failed: %v", err)
|
||||||
|
@ -240,29 +242,19 @@ func renderFile(lang string, w gemini.ResponseWriter, r *gemini.Request, client
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
category := ""
|
w.SetMediaType("text/gemini")
|
||||||
for i, cat := range file.File.Category {
|
tpl := pongo2.Must(pongo2.FromFile("templates/page.gmi"))
|
||||||
category = category + fmt.Sprintf("=> /%s/f/%s .%s└─ %s\n",
|
page, err := tpl.Execute(pongo2.Context{"lang": lang, "file": file})
|
||||||
lang,
|
if err != nil {
|
||||||
strings.Join(file.File.Category[:i+1], "/"),
|
log.Fatalf("template failed: %v", err)
|
||||||
strings.Repeat(" ", i),
|
return
|
||||||
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))
|
_, err = w.Write([]byte(page))
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(gemini.StatusTemporaryFailure, "Internal server error")
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func renderAllFiles(lang string, w gemini.ResponseWriter, client TreeManagerClient) {
|
func renderAllFiles(lang string, w gemini.ResponseWriter, client TreeManagerClient) {
|
||||||
|
@ -274,40 +266,51 @@ func renderAllFiles(lang string, w gemini.ResponseWriter, client TreeManagerClie
|
||||||
|
|
||||||
tree, err := client.GetSummery(context.Background(), &tr)
|
tree, err := client.GetSummery(context.Background(), &tr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("client.GetSummery failed: %v", err)
|
|
||||||
w.WriteHeader(gemini.StatusTemporaryFailure, "Internal server error")
|
w.WriteHeader(gemini.StatusTemporaryFailure, "Internal server error")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
content := "# Arnas alkierios :: "
|
w.SetMediaType("text/gemini")
|
||||||
if lang == "sgs" {
|
tpl := pongo2.Must(pongo2.FromFile("templates/all_texts.gmi"))
|
||||||
content = content + "vėsė tekstā\n\n"
|
page, err := tpl.Execute(pongo2.Context{"lang": lang, "tree": tree})
|
||||||
} else {
|
if err != nil {
|
||||||
content = content + "all texts\n\n"
|
log.Fatalf("template failed: %v", err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, f := range tree.Files {
|
_, err = w.Write([]byte(page))
|
||||||
content = appendFileLink(lang, content, f)
|
if err != nil {
|
||||||
|
w.WriteHeader(gemini.StatusTemporaryFailure, "Internal server error")
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if lang == "sgs" {
|
func renderTag(lang string, w gemini.ResponseWriter, r *gemini.Request, client TreeManagerClient) {
|
||||||
content = content + "\n=> /sgs ← grīžtė"
|
urlParts := strings.Split(strings.Trim(r.URL.Path, "/"), "/")
|
||||||
} else {
|
tag := urlParts[len(urlParts)-1]
|
||||||
content = content + "\n=> /en ← back"
|
tagFilter := TreeRequest_Filter{Key: "tag", Value: tag}
|
||||||
|
filters := []*TreeRequest_Filter{&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.Write([]byte(content))
|
w.SetMediaType("text/gemini")
|
||||||
|
tpl := pongo2.Must(pongo2.FromFile("templates/tag.gmi"))
|
||||||
|
page, err := tpl.Execute(pongo2.Context{"lang": lang, "tree": tree, "tag": tag})
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("template failed: %v", err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func appendFileLink(lang string, content string, f *TreeFile) string {
|
_, err = w.Write([]byte(page))
|
||||||
content = content + fmt.Sprintf(
|
if err != nil {
|
||||||
"=> /%s/f/%s/%s/%s %s (%s)\n",
|
w.WriteHeader(gemini.StatusTemporaryFailure, "Internal server error")
|
||||||
lang,
|
return
|
||||||
strings.Join(f.Category, "/"),
|
}
|
||||||
f.Id,
|
|
||||||
strings.Replace(f.Name, ".md", ".gmi", 1),
|
|
||||||
f.Description,
|
|
||||||
f.Created,
|
|
||||||
)
|
|
||||||
return content
|
|
||||||
}
|
}
|
||||||
|
|
7
templates/all_texts.gmi
Normal file
7
templates/all_texts.gmi
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
{% import "macros.tpl" category_url, tag_url, text_url %}
|
||||||
|
# Arna alkierios :: {% if lang == "sgs" %}Vėsė tekstā{% else %}All texts{% endif %}
|
||||||
|
|
||||||
|
{% for file in tree.Files %}{{ text_url(lang, file) }}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
=> {% if lang == "sgs" %}/sgs 🏠 grīžtė{% else %}/en ← back{% endif %}
|
|
@ -1,10 +1,18 @@
|
||||||
{% import "macros.tpl" category_url, text_url %}
|
{% import "macros.tpl" category_url, tag_url, text_url %}
|
||||||
# Arna alkierios :: {{ path }}
|
# Arna alkierios :: {{ path }}
|
||||||
|
|
||||||
{% if indexFile %}{{ indexFile.Content }}{% endif %}
|
{% if indexFile %}{{ indexFile.Content }}
|
||||||
|
|
||||||
{% for file in tree.RootFiles %}{{ text_url(lang, file) }} {% endfor %}
|
🌙 {{ indexFile.File.Created}}
|
||||||
|
{{ indexFile.File.Copyright }}{% endif %}
|
||||||
|
|
||||||
|
{% for file in tree.RootFiles %}{{ text_url(lang, file) }}
|
||||||
|
{% endfor %}
|
||||||
{% if tree.Categories %}### {% if lang == "sgs" %}Kateguorėjės{% else %}Categories{% endif %}
|
{% if tree.Categories %}### {% if lang == "sgs" %}Kateguorėjės{% else %}Categories{% endif %}
|
||||||
{% for cat, count in tree.Categories %}{{ category_url(lang, cat, cat, count) }}
|
{% for cat, count in tree.Categories %}{{ category_url(lang, tree.Path|add:"/"|add:cat, cat, count) }}
|
||||||
{% endfor %} {% endif %}
|
{% endfor %} {% endif %}
|
||||||
|
{% if tree.Tags %}### {% if lang == "sgs" %}Žīmas{% else %}Tags{% endif %}
|
||||||
|
{% for tag, count in tree.Tags %}{{ tag_url(lang, tag, count) }}
|
||||||
|
{% endfor %} {% endif %}
|
||||||
|
{% if tree.RootPath %}{{ category_url(lang, tree.RootPath, tree.RootPath, 0) }}{% endif %}
|
||||||
=> {% if lang == "sgs" %}/sgs 🏠 nomėi{% else %}/en 🏠 home{% endif %}
|
=> {% if lang == "sgs" %}/sgs 🏠 nomėi{% else %}/en 🏠 home{% endif %}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{% macro category_url(lang, path, category, count) export %}=> /{{ lang }}/f/{{ path }} {{ category }} ({{ count }}) {% endmacro %}
|
{% macro category_url(lang, path, category, count) export %}=> /{{ lang }}/f/{{ path }} 🌿 {{ category }}{% if count %} ({{ count }}){% endif %} {% endmacro %}
|
||||||
|
|
||||||
{% macro tag_url(lang, tag, count) export %}=> /{{ lang }}/t/{{ tag }} {{ tag }} ({{ 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 %}
|
{% macro text_url(lang, file) export %}=> /{{ lang }}/f/{{ file.CategoriesAsUrl() }}/{{ file.Id }}/{{ file.GmiName() }} ✒ {{ file.Description }} ({{ file.Created }}) {% endmacro %}
|
||||||
|
|
13
templates/page.gmi
Normal file
13
templates/page.gmi
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
{% import "macros.tpl" category_url, tag_url, text_url %}
|
||||||
|
# Arna alkierios :: {{ file.File.Description }}
|
||||||
|
|
||||||
|
{{ file.Content }}
|
||||||
|
|
||||||
|
🌙 {{ file.File.Created}}
|
||||||
|
{{ file.File.Copyright }}
|
||||||
|
|
||||||
|
{% if file.File.Tags %}### {% if lang == "sgs" %}Žīmas{% else %}Tags{% endif %}
|
||||||
|
{% for tag in file.File.Tags %}{{ tag_url(lang, tag, 0) }}
|
||||||
|
{% endfor %} {% endif %}
|
||||||
|
{{ category_url(lang, file.File.CategoryPath, file.File.Category|last, 0) }}
|
||||||
|
=> {% if lang == "sgs" %}/sgs 🏠 nomėi{% else %}/en 🏠 home{% endif %}
|
9
templates/tag.gmi
Normal file
9
templates/tag.gmi
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
{% import "macros.tpl" category_url, tag_url, text_url %}
|
||||||
|
# Arna alkierios :: [{{ tag }}]
|
||||||
|
|
||||||
|
{% for file in tree.Files %}{{ text_url(lang, file) }}
|
||||||
|
{% endfor %}
|
||||||
|
{% if tree.Tags %}### {% if lang == "sgs" %}Žīmas{% else %}Tags{% endif %}
|
||||||
|
{% for tag, count in tree.Tags %}{{ tag_url(lang, tag, count) }}
|
||||||
|
{% endfor %} {% endif %}
|
||||||
|
=> {% if lang == "sgs" %}/sgs 🏠 nomėi{% else %}/en 🏠 home{% endif %}
|
23
tree.pb.go
23
tree.pb.go
|
@ -234,6 +234,8 @@ type Tree struct {
|
||||||
RootFiles []*TreeFile `protobuf:"bytes,4,rep,name=rootFiles,proto3" json:"rootFiles,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"`
|
||||||
|
Path string `protobuf:"bytes,5,opt,name=path,proto3" json:"path,omitempty"`
|
||||||
|
RootPath string `protobuf:"bytes,6,opt,name=rootPath,proto3" json:"rootPath,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Tree) Reset() {
|
func (x *Tree) Reset() {
|
||||||
|
@ -296,6 +298,20 @@ func (x *Tree) GetCategories() map[string]int32 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *Tree) GetPath() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Path
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Tree) GetRootPath() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.RootPath
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
type FileContent struct {
|
type FileContent struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
|
@ -434,7 +450,7 @@ 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, 0xb8, 0x02, 0x0a, 0x04, 0x54, 0x72, 0x65, 0x65, 0x12,
|
0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x22, 0xe8, 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, 0x2c, 0x0a, 0x09, 0x72, 0x6f, 0x6f, 0x74, 0x46, 0x69, 0x6c,
|
0x66, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x2c, 0x0a, 0x09, 0x72, 0x6f, 0x6f, 0x74, 0x46, 0x69, 0x6c,
|
||||||
|
@ -446,7 +462,10 @@ var file_tree_proto_rawDesc = []byte{
|
||||||
0x0a, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28,
|
0x0a, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28,
|
||||||
0x0b, 0x32, 0x1a, 0x2e, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x2e, 0x43, 0x61,
|
0x0b, 0x32, 0x1a, 0x2e, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x2e, 0x43, 0x61,
|
||||||
0x74, 0x65, 0x67, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x63,
|
0x74, 0x65, 0x67, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x63,
|
||||||
0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x1a, 0x37, 0x0a, 0x09, 0x54, 0x61, 0x67,
|
0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74,
|
||||||
|
0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x1a, 0x0a,
|
||||||
|
0x08, 0x72, 0x6f, 0x6f, 0x74, 0x50, 0x61, 0x74, 0x68, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||||
|
0x08, 0x72, 0x6f, 0x6f, 0x74, 0x50, 0x61, 0x74, 0x68, 0x1a, 0x37, 0x0a, 0x09, 0x54, 0x61, 0x67,
|
||||||
0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20,
|
0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20,
|
||||||
0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75,
|
0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75,
|
||||||
0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02,
|
0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02,
|
||||||
|
|
|
@ -42,6 +42,8 @@ message Tree {
|
||||||
repeated TreeFile rootFiles = 4;
|
repeated TreeFile rootFiles = 4;
|
||||||
map<string, int32> tags = 2;
|
map<string, int32> tags = 2;
|
||||||
map<string, int32> categories = 3;
|
map<string, int32> categories = 3;
|
||||||
|
string path = 5;
|
||||||
|
string rootPath = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
message FileContent {
|
message FileContent {
|
||||||
|
|
Loading…
Reference in a new issue