refactor to have capsule per default language

This commit is contained in:
Arnas Udovic 2024-07-11 16:22:30 +03:00
parent 314801b838
commit d9602f5c48
13 changed files with 154 additions and 183 deletions

View file

@ -7,14 +7,14 @@ My capsule in Gemini space. Built with zord-tree support
## TODO ## TODO
* main.go:173 add content type by extension
* refactor layout * refactor layout
* remove capsule title from simple page
* security * security
* citata from some file * citata from some file
* add pagehint counter in abcex * add pagehint counter in abcex
* add gallery categories. index.md with secret to dynamic generators on build * add gallery categories. index.md with secret to dynamic generators on build
__DONE__ __DONE__
* remove capsule title from simple page
* main.go:173 add content type by extension
* add image or other file not `gmi` download * add image or other file not `gmi` download
* feed * feed
* add category view * add category view

28
dict.go Normal file
View file

@ -0,0 +1,28 @@
package main
type dict struct {
hostname string
languageEn string
searchStr string
}
var EN = dict{
hostname: "en.arns.lt",
languageEn: "English",
searchStr: "Input searching tag, created date or word in description",
}
var SGS = dict{
hostname: "en.arns.lt",
languageEn: "Samogitian",
searchStr: "Ivesk ėiškuoma žīma, sokūrėma data arba žuodi ėš aprašīma",
}
func Dict() dict {
dictMap := map[string]dict{
"en": EN,
"sgs": SGS,
}
return dictMap[defaultLang]
}

148
main.go
View file

@ -4,8 +4,6 @@ import (
"context" "context"
"flag" "flag"
"fmt" "fmt"
"git.sr.ht/~adnano/go-gemini"
"google.golang.org/grpc/credentials/insecure"
"io" "io"
"log" "log"
"mime" "mime"
@ -14,10 +12,12 @@ import (
"strings" "strings"
"time" "time"
"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" "github.com/flosch/pongo2/v6"
"github.com/gorilla/feeds" "github.com/gorilla/feeds"
"google.golang.org/grpc" "google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
) )
var ( var (
@ -26,19 +26,24 @@ var (
fileSrvHost string fileSrvHost string
fileSrvPort string fileSrvPort string
certificatePath string certificatePath string
defaultLang string
supportedLang string
key = "WgiPGpt5wM6SVEWo5iqI" key = "WgiPGpt5wM6SVEWo5iqI"
) )
const DefaultLang = "sgs"
var SupportedLang = []string{"en", "sgs", "lt", "prg", "eo"}
func init() { func init() {
flag.StringVar(&hostname, "hostname", "", "capsule hostname") flag.StringVar(&hostname, "hostname", "", "capsule hostname")
flag.StringVar(&port, "port", "1965", "capsule port") flag.StringVar(&port, "port", "1965", "capsule port")
flag.StringVar(&certificatePath, "certificatePath", "", "capsule certificate path") flag.StringVar(&certificatePath, "certificatePath", "", "capsule certificate path")
flag.StringVar(&fileSrvHost, "fileSrvHost", "", "file push server host") flag.StringVar(&fileSrvHost, "fileSrvHost", "", "file push server host")
flag.StringVar(&fileSrvPort, "fileSrvPort", "", "file push server port") flag.StringVar(&fileSrvPort, "fileSrvPort", "", "file push server port")
flag.StringVar(&defaultLang, "defaultLang", "", "default language, ex. sgs")
flag.StringVar(
&supportedLang,
"supportedLang",
"",
"other supported languages separated by |, ex., prg|lt",
)
flag.StringVar(&key, "key", "", "secret key to communicate admin") flag.StringVar(&key, "key", "", "secret key to communicate admin")
flag.Parse() flag.Parse()
} }
@ -79,7 +84,10 @@ func processRebuild(ctx context.Context, w gemini.ResponseWriter, r *gemini.Requ
w.WriteHeader(gemini.StatusServerUnavailable, "Don't wake up the dragons :-*") w.WriteHeader(gemini.StatusServerUnavailable, "Don't wake up the dragons :-*")
} }
conn, err := grpc.Dial(fileSrvHost+":"+fileSrvPort, grpc.WithTransportCredentials(insecure.NewCredentials())) conn, err := grpc.Dial(
fileSrvHost+":"+fileSrvPort,
grpc.WithTransportCredentials(insecure.NewCredentials()),
)
if err != nil { if err != nil {
w.WriteHeader(gemini.StatusTemporaryFailure, "Internal server error") w.WriteHeader(gemini.StatusTemporaryFailure, "Internal server error")
log.Fatal(err) log.Fatal(err)
@ -113,14 +121,10 @@ func processFavicon(_ context.Context, w gemini.ResponseWriter, _ *gemini.Reques
func process(_ context.Context, w gemini.ResponseWriter, r *gemini.Request) { func process(_ context.Context, w gemini.ResponseWriter, r *gemini.Request) {
log.Println("-> " + r.URL.Path) log.Println("-> " + r.URL.Path)
lang := regexp.MustCompile(`^/(sgs|en)`).FindString(r.URL.Path) conn, err := grpc.Dial(
if lang != "" { fileSrvHost+":"+fileSrvPort,
lang = lang[1:] grpc.WithTransportCredentials(insecure.NewCredentials()),
} else { )
lang = DefaultLang
}
conn, err := grpc.Dial(fileSrvHost+":"+fileSrvPort, grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil { if err != nil {
w.WriteHeader(gemini.StatusTemporaryFailure, "Internal server error") w.WriteHeader(gemini.StatusTemporaryFailure, "Internal server error")
log.Fatal(err) log.Fatal(err)
@ -129,23 +133,23 @@ func process(_ context.Context, w gemini.ResponseWriter, r *gemini.Request) {
defer conn.Close() defer conn.Close()
client := NewTreeManagerClient(conn) client := NewTreeManagerClient(conn)
langs := strings.Join(SupportedLang, "|")
switch { switch {
case "/" == r.URL.Path: case "/" == r.URL.Path:
w.WriteHeader(gemini.StatusPermanentRedirect, "/"+DefaultLang) renderIndex(w, client)
case regexp.MustCompile(`^/(` + langs + `)/?$`).MatchString(r.URL.Path): case regexp.MustCompile(`^/atom.xml$`).MatchString(r.URL.Path):
renderIndex(lang, w, client) renderFeed(w, r, client)
case regexp.MustCompile(`^/(` + langs + `)/atom.xml$`).MatchString(r.URL.Path): case regexp.MustCompile(`^/a/?$`).MatchString(r.URL.Path):
renderFeed(lang, w, r, client) renderAbout(w)
case regexp.MustCompile(`^/(` + langs + `)/a/?$`).MatchString(r.URL.Path):
renderAbout(lang, w)
case regexp.MustCompile(`^/(` + langs + `)/s/?$`).MatchString(r.URL.Path): case regexp.MustCompile(`^/(` + langs + `)/s/?$`).MatchString(r.URL.Path):
renderSearch(lang, w, r, client) renderSearch(lang, w, r, client)
case regexp.MustCompile(`^/(` + langs + `)/f/?$`).MatchString(r.URL.Path): case regexp.MustCompile(`^/(` + langs + `)/f/?$`).MatchString(r.URL.Path):
renderAllFiles(lang, w, client) renderAllFiles(lang, w, client)
case regexp.MustCompile(`^/(` + langs + `)/f/([\p{L}\d_+.]+/)+[\d\w]+/index.gmi$`).MatchString(r.URL.Path): case regexp.MustCompile(`^/(` + langs + `)/f/([\p{L}\d_+.]+/)+[\d\w]+/index.gmi$`).MatchString(r.URL.Path):
urlParts := strings.Split(r.URL.Path, "/") urlParts := strings.Split(r.URL.Path, "/")
w.WriteHeader(gemini.StatusPermanentRedirect, strings.Join(urlParts[:(len(urlParts)-2)], "/")) w.WriteHeader(
gemini.StatusPermanentRedirect,
strings.Join(urlParts[:(len(urlParts)-2)], "/"),
)
case regexp.MustCompile(`^/(` + langs + `)/f/([\p{L}\d_+.]+/)+[\d\w]+/[\p{L}\d_+.]+.gmi$`).MatchString(r.URL.Path): case regexp.MustCompile(`^/(` + langs + `)/f/([\p{L}\d_+.]+/)+[\d\w]+/[\p{L}\d_+.]+.gmi$`).MatchString(r.URL.Path):
renderFile(lang, w, r, client) renderFile(lang, w, r, client)
case regexp.MustCompile(`^/(` + langs + `)/f/[\p{L}\d_+.]+(/[\p{L}\d_+.]+)*/?$`).MatchString(r.URL.Path): case regexp.MustCompile(`^/(` + langs + `)/f/[\p{L}\d_+.]+(/[\p{L}\d_+.]+)*/?$`).MatchString(r.URL.Path):
@ -157,7 +161,6 @@ func process(_ context.Context, w gemini.ResponseWriter, r *gemini.Request) {
default: default:
w.WriteHeader(gemini.StatusNotFound, "Out of space") w.WriteHeader(gemini.StatusNotFound, "Out of space")
} }
} }
func downloadAttachment(w gemini.ResponseWriter, r *gemini.Request, client TreeManagerClient) { func downloadAttachment(w gemini.ResponseWriter, r *gemini.Request, client TreeManagerClient) {
@ -190,16 +193,18 @@ func downloadAttachment(w gemini.ResponseWriter, r *gemini.Request, client TreeM
} }
} }
func renderIndex(lang string, w gemini.ResponseWriter, client TreeManagerClient) { func getLangFilters() []*TreeRequest_Filter {
filters := []*TreeRequest_Filter{{Key: "lang", Value: lang}} filters := []*TreeRequest_Filter{{Key: "lang", Value: defaultLang}}
if lang == "sgs" { for _, l := range strings.Split(supportedLang, "|") {
for _, l := range []string{"lt", "prg", "eo"} { filters = append(filters, &TreeRequest_Filter{Key: "lang", Value: l})
filters = append(filters, &TreeRequest_Filter{Key: "lang", Value: l})
}
} }
return filters
}
func renderIndex(w gemini.ResponseWriter, client TreeManagerClient) {
path := "" path := ""
tr := TreeRequest{Path: &path, Filter: filters} tr := TreeRequest{Path: &path, Filter: getLangFilters()}
tree, err := client.GetSummery(context.Background(), &tr) tree, err := client.GetSummery(context.Background(), &tr)
if err != nil { if err != nil {
@ -208,8 +213,10 @@ func renderIndex(lang string, w gemini.ResponseWriter, client TreeManagerClient)
} }
w.SetMediaType("text/gemini") w.SetMediaType("text/gemini")
tpl := pongo2.Must(pongo2.FromFile(fmt.Sprintf("templates/%s/index.gmi", lang))) tpl := pongo2.Must(pongo2.FromFile(fmt.Sprintf("templates/%s/index.gmi", defaultLang)))
page, err := tpl.Execute(pongo2.Context{"tree": tree, "lang": lang, "lastFiles": GetLastFiles(tree.Files)}) page, err := tpl.Execute(
pongo2.Context{"tree": tree, "lang": defaultLang, "lastFiles": GetLastFiles(tree.Files)},
)
if err != nil { if err != nil {
log.Fatalf("template failed: %v", err) log.Fatalf("template failed: %v", err)
return return
@ -222,16 +229,9 @@ func renderIndex(lang string, w gemini.ResponseWriter, client TreeManagerClient)
} }
} }
func renderFeed(lang string, w gemini.ResponseWriter, r *gemini.Request, client TreeManagerClient) { func renderFeed(w gemini.ResponseWriter, r *gemini.Request, client TreeManagerClient) {
filters := []*TreeRequest_Filter{{Key: "lang", Value: lang}}
if lang == "sgs" {
for _, l := range []string{"lt", "prg", "eo"} {
filters = append(filters, &TreeRequest_Filter{Key: "lang", Value: l})
}
}
path := "" path := ""
tr := TreeRequest{Path: &path, Filter: filters} tr := TreeRequest{Path: &path, Filter: getLangFilters()}
tree, err := client.GetSummery(context.Background(), &tr) tree, err := client.GetSummery(context.Background(), &tr)
if err != nil { if err != nil {
@ -241,14 +241,10 @@ func renderFeed(lang string, w gemini.ResponseWriter, r *gemini.Request, client
w.SetMediaType("application/atom+xml") w.SetMediaType("application/atom+xml")
now := time.Now() now := time.Now()
language := "Samogitian"
if lang == "en" {
language = "English"
}
feed := &feeds.Feed{ feed := &feeds.Feed{
Title: "\U0001F31B Arna alkierios [" + lang + "]", Title: "\U0001F31B Arna alkierios [" + defaultLang + "]",
Link: &feeds.Link{Href: "gemini://arns.lt/" + lang}, Link: &feeds.Link{Href: "gemini://" + Dict().hostname},
Description: "personal gemini capsule by Arns Udovič [" + language + " version]", Description: "personal gemini capsule by Arns Udovič [" + Dict().languageEn + " version]",
Author: &feeds.Author{Name: "Arns Udovič", Email: "zordsdavini@arns.lt"}, Author: &feeds.Author{Name: "Arns Udovič", Email: "zordsdavini@arns.lt"},
Created: now, Created: now,
} }
@ -260,9 +256,8 @@ func renderFeed(lang string, w gemini.ResponseWriter, r *gemini.Request, client
feed.Add( feed.Add(
&feeds.Item{ &feeds.Item{
Title: file.Description, Title: file.Description,
Link: &feeds.Link{Href: fmt.Sprintf("gemini://%s/%s/f%s/%s/%s", Link: &feeds.Link{Href: fmt.Sprintf("gemini://%s/f%s/%s/%s",
r.URL.Host, r.URL.Host,
lang,
file.CategoryPath(), file.CategoryPath(),
file.Id, file.Id,
file.GmiName(), file.GmiName(),
@ -291,9 +286,9 @@ func renderFeed(lang string, w gemini.ResponseWriter, r *gemini.Request, client
} }
} }
func renderAbout(lang string, w gemini.ResponseWriter) { func renderAbout(w gemini.ResponseWriter) {
w.SetMediaType("text/gemini") w.SetMediaType("text/gemini")
tpl := pongo2.Must(pongo2.FromFile(fmt.Sprintf("templates/%s/about.gmi", lang))) tpl := pongo2.Must(pongo2.FromFile(fmt.Sprintf("templates/%s/about.gmi", defaultLang)))
page, err := tpl.Execute(pongo2.Context{}) page, err := tpl.Execute(pongo2.Context{})
if err != nil { if err != nil {
log.Fatalf("template failed: %v", err) log.Fatalf("template failed: %v", err)
@ -306,14 +301,14 @@ func renderAbout(lang string, w gemini.ResponseWriter) {
} }
} }
func renderSearch(lang string, w gemini.ResponseWriter, r *gemini.Request, client TreeManagerClient) { func renderSearch(
w gemini.ResponseWriter,
r *gemini.Request,
client TreeManagerClient,
) {
q, err := gemini.QueryUnescape(r.URL.RawQuery) q, err := gemini.QueryUnescape(r.URL.RawQuery)
if err != nil || q == "" { if err != nil || q == "" {
searchStr := "Input searching tag, created date or word in description" w.WriteHeader(gemini.StatusInput, Dict().searchStr)
if lang == "sgs" {
searchStr = "Ivesk ėiškuoma žīma, sokūrėma data arba žuodi ėš aprašīma"
}
w.WriteHeader(gemini.StatusInput, searchStr)
return return
} }
@ -333,7 +328,7 @@ func renderSearch(lang string, w gemini.ResponseWriter, r *gemini.Request, clien
w.SetMediaType("text/gemini") w.SetMediaType("text/gemini")
tpl := pongo2.Must(pongo2.FromFile("templates/search.gmi")) tpl := pongo2.Must(pongo2.FromFile("templates/search.gmi"))
page, err := tpl.Execute(pongo2.Context{"lang": lang, "tree": tree, "q": q}) page, err := tpl.Execute(pongo2.Context{"lang": defaultLang, "tree": tree, "q": q})
if err != nil { if err != nil {
log.Fatalf("template failed: %v", err) log.Fatalf("template failed: %v", err)
return return
@ -346,7 +341,11 @@ func renderSearch(lang string, w gemini.ResponseWriter, r *gemini.Request, clien
} }
} }
func renderCategory(lang string, w gemini.ResponseWriter, r *gemini.Request, client TreeManagerClient) { func renderCategory(
w gemini.ResponseWriter,
r *gemini.Request,
client TreeManagerClient,
) {
urlParts := strings.Split(strings.Trim(r.URL.Path, "/"), "/") urlParts := strings.Split(strings.Trim(r.URL.Path, "/"), "/")
path := "/" + strings.Join(urlParts[2:], "/") path := "/" + strings.Join(urlParts[2:], "/")
@ -371,7 +370,9 @@ 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"))
page, err := tpl.Execute(pongo2.Context{"lang": lang, "tree": tree, "path": path, "indexFile": file}) page, err := tpl.Execute(
pongo2.Context{"lang": defaultLang, "tree": tree, "path": path, "indexFile": file},
)
if err != nil { if err != nil {
log.Fatalf("template failed: %v", err) log.Fatalf("template failed: %v", err)
return return
@ -384,7 +385,7 @@ func renderCategory(lang string, w gemini.ResponseWriter, r *gemini.Request, cli
} }
} }
func renderFile(lang string, w gemini.ResponseWriter, r *gemini.Request, client TreeManagerClient) { func renderFile(w gemini.ResponseWriter, r *gemini.Request, client TreeManagerClient) {
urlParts := strings.Split(r.URL.Path, "/") urlParts := strings.Split(r.URL.Path, "/")
id := urlParts[len(urlParts)-2] id := urlParts[len(urlParts)-2]
@ -398,7 +399,7 @@ func renderFile(lang string, w gemini.ResponseWriter, r *gemini.Request, client
w.SetMediaType("text/gemini") w.SetMediaType("text/gemini")
tpl := pongo2.Must(pongo2.FromFile("templates/page.gmi")) tpl := pongo2.Must(pongo2.FromFile("templates/page.gmi"))
page, err := tpl.Execute(pongo2.Context{"lang": lang, "file": file}) page, err := tpl.Execute(pongo2.Context{"lang": defaultLang, "file": file})
if err != nil { if err != nil {
log.Fatalf("template failed: %v", err) log.Fatalf("template failed: %v", err)
return return
@ -411,16 +412,9 @@ func renderFile(lang string, w gemini.ResponseWriter, r *gemini.Request, client
} }
} }
func renderAllFiles(lang string, w gemini.ResponseWriter, client TreeManagerClient) { func renderAllFiles(w gemini.ResponseWriter, client TreeManagerClient) {
filters := []*TreeRequest_Filter{{Key: "lang", Value: lang}}
if lang == "sgs" {
for _, l := range []string{"lt", "prg", "eo"} {
filters = append(filters, &TreeRequest_Filter{Key: "lang", Value: l})
}
}
path := "" path := ""
tr := TreeRequest{Path: &path, Filter: filters} tr := TreeRequest{Path: &path, Filter: getLangFilters()}
tree, err := client.GetSummery(context.Background(), &tr) tree, err := client.GetSummery(context.Background(), &tr)
if err != nil { if err != nil {
@ -430,7 +424,7 @@ func renderAllFiles(lang string, w gemini.ResponseWriter, client TreeManagerClie
w.SetMediaType("text/gemini") w.SetMediaType("text/gemini")
tpl := pongo2.Must(pongo2.FromFile("templates/all_texts.gmi")) tpl := pongo2.Must(pongo2.FromFile("templates/all_texts.gmi"))
page, err := tpl.Execute(pongo2.Context{"lang": lang, "tree": tree}) page, err := tpl.Execute(pongo2.Context{"lang": defaultLang, "tree": tree})
if err != nil { if err != nil {
log.Fatalf("template failed: %v", err) log.Fatalf("template failed: %v", err)
return return
@ -443,7 +437,7 @@ func renderAllFiles(lang string, w gemini.ResponseWriter, client TreeManagerClie
} }
} }
func renderTag(lang string, w gemini.ResponseWriter, r *gemini.Request, client TreeManagerClient) { func renderTag(w gemini.ResponseWriter, r *gemini.Request, client TreeManagerClient) {
urlParts := strings.Split(strings.Trim(r.URL.Path, "/"), "/") urlParts := strings.Split(strings.Trim(r.URL.Path, "/"), "/")
tag := urlParts[len(urlParts)-1] tag := urlParts[len(urlParts)-1]
tagFilter := TreeRequest_Filter{Key: "tag", Value: tag} tagFilter := TreeRequest_Filter{Key: "tag", Value: tag}
@ -460,7 +454,7 @@ func renderTag(lang string, w gemini.ResponseWriter, r *gemini.Request, client T
w.SetMediaType("text/gemini") w.SetMediaType("text/gemini")
tpl := pongo2.Must(pongo2.FromFile("templates/tag.gmi")) tpl := pongo2.Must(pongo2.FromFile("templates/tag.gmi"))
page, err := tpl.Execute(pongo2.Context{"lang": lang, "tree": tree, "tag": tag}) page, err := tpl.Execute(pongo2.Context{"lang": defaultLang, "tree": tree, "tag": tag})
if err != nil { if err != nil {
log.Fatalf("template failed: %v", err) log.Fatalf("template failed: %v", err)
return return

View file

@ -1,6 +1,6 @@
{% import "macros.tpl" category_url, tag_url, text_url, logo %} {% import "macros.tpl" category_url, tag_url, text_url, logo, home %}
# {% if lang == "sgs" %}Vėsė tekstā{% else %}All texts{% endif %} # {% if lang == "sgs" %}Vėsė tekstā{% else %}All texts{% endif %}
{% for file in tree.Files %}{{ text_url(lang, file) }}{% endfor %} {% for file in tree.Files %}{{ text_url(file) }}{% endfor %}
=> {% if lang == "sgs" %}/sgs ← grīžtė{% else %}/en ← back{% endif %} {{ home(lang) }}

View file

@ -1,17 +1,18 @@
{% import "macros.tpl" category_url, tag_url, text_url, logo %} {% import "macros.tpl" category_url, tag_url, text_url, logo, home %}
# {{ path }} # {{ path }}
{% if indexFile %}{{ indexFile.FormatContent()|safe }} {% if indexFile %}{{ indexFile.FormatContent()|safe }}
🌙{{ indexFile.File.Created}} 🌙{{ indexFile.File.Created}}
{{ indexFile.File.Copyright }}{% endif %} {{ indexFile.File.Copyright }}
{{ indexFile.File.Lang }}{% endif %}
{% for file in tree.RootFiles %}{% if file.Name != "index.md" %}{{ text_url(lang, file) }}{% endif %}{% endfor %} {% for file in tree.RootFiles %}{% if file.Name != "index.md" %}{{ text_url(file) }}{% endif %}{% 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, tree.Path|add:"/"|add:cat, cat, count) }} {% for cat, count in tree.Categories %}{{ category_url(tree.Path|add:"/"|add:cat, cat, count) }}
{% endfor %} {% endif %} {% endfor %} {% endif %}
{% if tree.Tags %}### {% if lang == "sgs" %}Žīmas{% else %}Tags{% endif %} {% if tree.Tags %}### {% if lang == "sgs" %}Žīmas{% else %}Tags{% endif %}
{% for tag, count in tree.Tags %}{{ tag_url(lang, tag, count) }} {% for tag, count in tree.Tags %}{{ tag_url(tag, count) }}
{% endfor %} {% endif %} {% endfor %} {% endif %}
{% if tree.RootPath %}{{ category_url(lang, tree.RootPath, tree.RootPath, 0) }}{% endif %} {% if tree.RootPath %}{{ category_url(tree.RootPath, tree.RootPath, 0) }}{% endif %}
=> {% if lang == "sgs" %}/sgs 🏠 nomėi{% else %}/en 🏠 home{% endif %} {{ home(lang) }}

View file

@ -1,9 +1,9 @@
{% import "../macros.tpl" logo %} {% import "../macros.tpl" logo, home %}
# About # About
I am Arns Udovič, also you can find me by Zordsdavini. I am Arns Udovič, also you can find me by Zordsdavini.
=> /sgs/a žemaitėškā => gemini://arns.lt/a žemaitėškā
I am Samogitian, a small ethnic group in west part of Lithuania, but I live in Vilnius. Main my ideas are concentrated about Samogitian language and its spreading and standardization. I work a lot to propagate common writing to Samogitians. I am Samogitian, a small ethnic group in west part of Lithuania, but I live in Vilnius. Main my ideas are concentrated about Samogitian language and its spreading and standardization. I work a lot to propagate common writing to Samogitians.
@ -14,7 +14,8 @@ My religion is Nature and I believe what Earth is alive.
### Contact me ### Contact me
=> mailto:zordsdavini@arns.lt E-mail => mailto:zordsdavini@arns.lt E-mail
=> https://mastodon.social/@zordsdavini @zordsdavini@mastodon.social => https://s.arns.lt/@zordsdavini @zordsdavini@s.arns.lt
=> https://tv.arns.lt/@zordsdavini @zordsdavini@tv.arns.lt
## About capsule ## About capsule
@ -34,29 +35,4 @@ From this service it is served to gemini service what is written in Go, too, or
=> https://g.arns.lt/zordsdavini/arns-lt-gemini gemini service => https://g.arns.lt/zordsdavini/arns-lt-gemini gemini service
=> https://arns.lt Arna alkierios HTTP version => https://arns.lt Arna alkierios HTTP version
## Other projects {{ home('en') }}
### Samogitian
I am the member of Samogitian cultural society. To "legalize" my work on Samogitian language I created Institute of Samogitian language. In name of institute I do various stuff in IT to standardize Samogitian. Best finished projects:
=> https://bat-smg.wikipedia.org/wiki/P%C4%97rms_poslapis Wikipedia in Samogitian
=> https://iso639-3.sil.org/code/sgs ISO 639 code for Samogitian language "sgs"
Other links to works with Samogitian:
=> https://žemaitėjė.lt Institute of Samogitian language
=> https://ruoda.lt newspaper "Ruoda"
=> https://zkz.lt dictionary of Samogitian
### IT
=> https://kplaner.arns.lt Planner written on Python with my wife
=> https://odysee.com/@qtile-tv:0
### future plans
=> https://karmagiai.lt RPG game "Kariai ir magai" (similar to DnD, Liethuanian version) computerization (or helper to count)
=> https://vytines.lt winding tape automatization
=> https://sieps.lt helper app for inventorization
=> https://preferansas.lt card game Preferances Lithuanian edition
=> /en ← back

View file

@ -3,25 +3,21 @@
Welcome to my capsule in Gemini space. {{ logo() }} Welcome to my capsule in Gemini space. {{ logo() }}
> Če turietom būtė mon pruotinga cėtata :-P => gemini://arns.lt Žemaitėška versėjė
=> / Žemaitėška versėjė
=> https://arns.lt http version => https://arns.lt http version
Main themes are spreaded by categories. Each file may have tags what can filter the tree. => /a about
=> /en/s search
=> /en/a about
{% if tree.Categories %}### Categories {% if tree.Categories %}### Categories
{% for cat, count in tree.Categories %} {% for cat, count in tree.Categories %}
{{ category_url(lang, cat, cat, count) }} {% endfor %} {% endif %} {{ category_url(cat, cat, count) }} {% endfor %} {% endif %}
{% if tree.Tags %}### Tags {% if tree.Tags %}### Tags
{% for tag, count in tree.Tags %} {% for tag, count in tree.Tags %}
{{ tag_url(lang, tag, count) }} {% endfor %} {% endif %} {{ tag_url(tag, count) }} {% endfor %} {% endif %}
{% if lastFiles %}### Last texts {% if lastFiles %}### Last texts
{% for file in lastFiles %}{{ text_url(lang, file) }}{% endfor %}{% endif %} {% for file in lastFiles %}{{ text_url(file) }}{% endfor %}{% endif %}
=> /en/f all texts ({{ tree.Files|length }}) => /f all texts ({{ tree.Files|length }})
=> /s search

View file

@ -1,8 +1,10 @@
{% macro category_url(lang, path, category, count) export %}=> /{{ lang }}/f/{{ path }} 🌿 {{ category }}{% if count %} ({{ count }}){% endif %} {% endmacro %} {% macro category_url(path, category, count) export %}=> /f/{{ path }} 🌿 {{ category }}{% if count %} ({{ count }}){% endif %} {% endmacro %}
{% macro tag_url(lang, tag, count) export %}=> /{{ lang }}/t/{{ tag }} 🏷 {{ tag }}{% if count %} ({{ count }}){% endif %} {% endmacro %} {% macro tag_url(tag, count) export %}=> /t/{{ tag }} 🏷 {{ tag }}{% if count %} ({{ count }}){% endif %} {% endmacro %}
{% macro text_url(lang, file) export %}=> /{{ lang }}/f/{{ file.CategoriesAsUrl() }}/{{ file.Id }}/{{ file.GmiName() }}{{ file.Description }} ({{ file.Created }}) {% macro text_url(file) export %}=> /f/{{ file.CategoriesAsUrl() }}/{{ file.Id }}/{{ file.GmiName() }}{{ file.Description }} ({{ file.Created }})
{% endmacro %} {% endmacro %}
{% macro logo() export %}🌛{% endmacro %} {% macro logo() export %}🌛{% endmacro %}
{% macro home(lang) export %}=> / 🏠 {% if lang == "sgs" %}nomėi{% else %}home{% endif %}{% endmacro %}

View file

@ -1,14 +1,16 @@
{% import "macros.tpl" category_url, tag_url, text_url, logo %} {% import "macros.tpl" category_url, tag_url, text_url, logo, home %}
# {{ file.File.Description }} # {{ file.File.Description }}
{% if file.File.Tags %}### {% if lang == "sgs" %}Žīmas{% else %}Tags{% endif %} {% if file.File.Tags %}### {% if lang == "sgs" %}Žīmas{% else %}Tags{% endif %}
{% for tag in file.File.Tags %}{{ tag_url(lang, tag, 0) }} {% for tag in file.File.Tags %}{{ tag_url(tag, 0) }}
{% endfor %} {% endif %} {% endfor %} {% endif %}
🌙{{ file.File.Created}} 🌙{{ file.File.Created}}
{{ file.File.Copyright }} {{ file.File.Copyright }}
{{ file.File.Lang }}
{{ file.FormatContent()|safe }} {{ file.FormatContent()|safe }}
{{ category_url(lang, file.File.CategoryPath, file.File.Category|last, 0) }} {{ category_url(file.File.CategoryPath, file.File.Category|last, 0) }}
=> {% if lang == "sgs" %}/sgs 🏠 nomėi{% else %}/en 🏠 home{% endif %}
{{ home(lang) }}

View file

@ -1,8 +1,8 @@
{% import "macros.tpl" text_url, logo %} {% import "macros.tpl" text_url, logo, home %}
# {% if lang == "sgs" %}Paėiška{% else %}Search{% endif %} # {% if lang == "sgs" %}Paėiška{% else %}Search{% endif %}
{% if lang == "sgs" %}Ėiškuota vagol{% else %}Searched by{% endif %}: {{ q }} {% 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 %} {% 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 %} {% for file in tree.Files %}{{ text_url(file) }} {% endfor %}{% endif %}
=> {% if lang == "sgs" %}/sgs ← grīžtė{% else %}/en ← back{% endif %} {{ home(lang) }}

View file

@ -1,9 +1,9 @@
{% import "../macros.tpl" logo %} {% import "../macros.tpl" logo %}
# Aple # Aple
Eso Udovič Arns, dā vadėnamo Zordsdavini arba Ousėnio. Eso Udovič Arns, dā vadėnamo Zordsdavini.
=> /en/a English version => gemini://en.arns.lt/a English version
Kraujė žemaitėška, bet laikaus Vėlniou. Pagrindėnės mėslės sokas aple žemaitiu kalbuos keravuojėma, anuos skleidėma ė pritaikīmus kompioterems. Daug darbū dėrbo, ka žėmaitē galietom rašītė bėndrinie rašībuo. Kraujė žemaitėška, bet laikaus Vėlniou. Pagrindėnės mėslės sokas aple žemaitiu kalbuos keravuojėma, anuos skleidėma ė pritaikīmus kompioterems. Daug darbū dėrbo, ka žėmaitē galietom rašītė bėndrinie rašībuo.
@ -14,7 +14,8 @@ Tāp pat eso gomtuos mīlietuos ė mėslėjo, ka Žemė ī gīva.
### parašīk mon ### parašīk mon
=> mailto:zordsdavini@arns.lt pašta skrabėkė => mailto:zordsdavini@arns.lt pašta skrabėkė
=> https://mastodon.social/@zordsdavini @zordsdavini@mastodon.social => https://s.arns.lt/@zordsdavini @zordsdavini@s.arns.lt
=> https://tv.arns.lt/@zordsdavini @zordsdavini@tv.arns.lt
## Aple alkierio ## Aple alkierio
@ -28,36 +29,11 @@ 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ā) => gemini://en.arns.lt/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
=> https://arns.lt Arna alkierios HTTP versėjuo => https://arns.lt Arna alkierios HTTP versėjuo
## Kėtė pruojektā {{ home('sgs') }}
### Žemaitėškė
Eso Žemaitiu koltūras draugėjės narīs. Ka „legalėzoutiuo“ sava darba žemaitiu kalbā, ikūriau Žemaitiu kalbuos instėtota. Instėtota vardo dėrėno vairius standartus IT ertie. Siekmingiausė bėngtė pruojektā:
=> https://bat-smg.wikipedia.org/wiki/P%C4%97rms_poslapis Vikipedėjė žemaitėška
=> https://iso639-3.sil.org/code/sgs ISO 639 kuods žemaitiu kalbā „sgs“
Kėtas nūruodas darbū so žemaitēs:
=> https://žemaitėjė.lt Žemaitiu kalbuos instėtota alkierios
=> https://ruoda.lt laikraštis „Ruoda“
=> https://zkz.lt žemaitiu kalbuos žuodīns
### IT
=> https://kplaner.arns.lt Planoutuos parašīts ont python'a karto so sava patė
=> https://odysee.com/@qtile-tv:0
### planūs
=> https://karmagiai.lt „Kariai ir magai“ internetėnė versėjė (arba gižielis skaitliavėmams)
=> https://vytines.lt vītėniu joustu vījėms ruoboto
=> https://sieps.lt gižielis inventuorėzacėjē
=> https://preferansas.lt internetėnė preferansa lietovėška versėjė
=> /sgs ← grīžtė

View file

@ -3,27 +3,23 @@
Sveikė atvīkėn i mona kapsolė Gemini ertie. {{ logo() }} Sveikė atvīkėn i mona kapsolė Gemini ertie. {{ logo() }}
> Če turietom būtė mon pruotinga cėtata :-P => gemini://en.arns.lt English version
=> /en English version
=> https://arns.lt http versėjė => https://arns.lt http versėjė
Pagrindėnės temas paskėrstītas par kateguorėjės. Kuožnos fails gal turietė žīmas, katruos gal atsėjuotė miedi. => /a aple
=> /sgs/s ėiškuok
=> /sgs/a aple
{% if tree.Categories %}### Kateguorėjės {% if tree.Categories %}### Kateguorėjės
{% for cat, count in tree.Categories %} {% for cat, count in tree.Categories %}
{{ category_url(lang, cat, cat, count) }} {% endfor %} {% endif %} {{ category_url(cat, cat, count) }} {% endfor %} {% endif %}
{% if tree.Tags %}### Žīmas {% if tree.Tags %}### Žīmas
{% for tag, count in tree.Tags %} {% for tag, count in tree.Tags %}
{{ tag_url(lang, tag, count) }} {% endfor %} {% endif %} {{ tag_url(tag, count) }} {% endfor %} {% endif %}
{% if lastFiles %}### Paskotėnē īrašā {% if lastFiles %}### Paskotėnē īrašā
{% for file in lastFiles %}{{ text_url(file.Lang, file) }}{% endfor %} {% for file in lastFiles %}{{ text_url(file) }}{% endfor %}
{% endif %} {% endif %}
=> /sgs/f vėsė straipsnē ({{ tree.Files|length }}) => /f vėsė straipsnē ({{ tree.Files|length }})
=> /s ėiškuok

View file

@ -1,8 +1,8 @@
{% import "macros.tpl" category_url, tag_url, text_url, logo %} {% import "macros.tpl" category_url, tag_url, text_url, logo, home %}
# [{{ tag }}] # [{{ tag }}]
{% for file in tree.Files %}{{ text_url(lang, file) }}{% endfor %} {% for file in tree.Files %}{{ text_url(file) }}{% endfor %}
{% if tree.Tags %}### {% if lang == "sgs" %}Žīmas{% else %}Tags{% endif %} {% if tree.Tags %}### {% if lang == "sgs" %}Žīmas{% else %}Tags{% endif %}
{% for tag, count in tree.Tags %}{{ tag_url(lang, tag, count) }} {% for tag, count in tree.Tags %}{{ tag_url(lang, tag, count) }}
{% endfor %} {% endif %} {% endfor %} {% endif %}
=> {% if lang == "sgs" %}/sgs 🏠 nomėi{% else %}/en 🏠 home{% endif %} {{ home(lang) }}