small pixel drawing of a pufferfish j3s.sh

total backend rewrite
Jes Olson j3s@c3f.net
Tue, 19 Sep 2023 20:10:54 -0500
commit

88bf8b34c1391c5568f3b8e2c07276445951f0ab

parent

843774d0b5129156f2a535bea3e3eeadb4731455

M go.modgo.mod

@@ -1,9 +1,14 @@

module git.j3s.sh/j3s.sh -go 1.16 +go 1.18 require ( filippo.io/age v1.1.1 github.com/SlyMarbo/rss v1.0.5 +) + +require ( + github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394 // indirect golang.org/x/crypto v0.6.0 // indirect + golang.org/x/sys v0.5.0 // indirect )
M go.sumgo.sum

@@ -1,57 +1,10 @@

-filippo.io/age v1.0.0 h1:V6q14n0mqYU3qKFkZ6oOaF9oXneOviS3ubXsSVBRSzc= -filippo.io/age v1.0.0/go.mod h1:PaX+Si/Sd5G8LgfCwldsSba3H1DDQZhIhFGkhbHaBq8= filippo.io/age v1.1.1 h1:pIpO7l151hCnQ4BdyBujnGP2YlUo0uj6sAVNHGBvXHg= filippo.io/age v1.1.1/go.mod h1:l03SrzDUrBkdBx8+IILdnn2KZysqQdbEBUQ4p3sqEQE= -filippo.io/edwards25519 v1.0.0-rc.1/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= -filippo.io/edwards25519 v1.0.0/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= -github.com/SlyMarbo/rss v1.0.3 h1:AnP63RxQxa0flEaiOryiTe5J5es0KCCfji6lU+rQ8tc= -github.com/SlyMarbo/rss v1.0.3/go.mod h1:w6Bhn1BZs91q4OlEnJVZEUNRJmlbFmV7BkAlgCN8ofM= github.com/SlyMarbo/rss v1.0.5 h1:DPcZ4aOXXHJ5yNLXY1q/57frIixMmAvTtLxDE3fsMEI= github.com/SlyMarbo/rss v1.0.5/go.mod h1:w6Bhn1BZs91q4OlEnJVZEUNRJmlbFmV7BkAlgCN8ofM= github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394 h1:OYA+5W64v3OgClL+IrOD63t4i/RW7RqrAVl9LTZ9UqQ= github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394/go.mod h1:Q8n74mJTIgjX4RBBcHnJ05h//6/k6foqmgE45jTQtxg= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d h1:sK3txAijHtOK88l68nt020reeT1ZdKLIYetKl95FzVY= -golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.4.0/go.mod h1:3quD/ATkf6oY+rnes5c3ExXTbLc8mueNue5/DoinL80= golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -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-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210903071746-97244b99971b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -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/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
M main.gomain.go

@@ -2,9 +2,11 @@ package main

import ( "bytes" + "embed" "fmt" "html/template" "io" + "io/fs" "log" "math/rand" "net/http"

@@ -21,6 +23,15 @@ "git.j3s.sh/j3s.sh/openlibrary"

"github.com/SlyMarbo/rss" ) +//go:embed thought +var thoughtFiles embed.FS + +//go:embed templates +var templateFiles embed.FS + +//go:embed static +var staticFiles embed.FS + // templateData is a mega-struct that gets // passed to every single template - put whatever // you want in it tbh.

@@ -29,16 +40,16 @@ // "data" is a global object that contains arbitrary

// data for use in templates. it's useful for it to be // global since it may need to be available in arbitrary // contexts. maybe that sucks. but idfk! -type templateData struct { +type templateDataStruct struct { Feeds []rss.Feed CurrentBooks *openlibrary.CurrentBooks } -var data templateData +var templateData templateDataStruct // the populate function populates the global "data" variable // with ... data. with which to pass into templates. -func (t *templateData) populate() { +func (t *templateDataStruct) populate() { // call for books first bc it's fast t.CurrentBooks = openlibrary.GetCurrentBooks() t.Feeds = feed.GetAllFeeds()

@@ -62,17 +73,14 @@ http.Redirect(w, r, url, 302)

} } -// this is here basically because /favicon.ico needs to be -// redirected to /static/favicon.ico -func faviconHandler(w http.ResponseWriter, r *http.Request) { - http.ServeFile(w, r, "static/favicon.ico") -} - func main() { - go data.populate() + go templateData.populate() - fs := http.FileServer(http.Dir("./static")) - http.Handle("/static/", http.StripPrefix("/static/", fs)) + fs, err := fs.Sub(staticFiles, "static") + if err != nil { + log.Fatal(err) + } + http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.FS(fs)))) // redirs up front - some of these are here for // historic reasons, others for utility

@@ -81,32 +89,32 @@ http.HandleFunc("/feeds", redirHandler("/feeds.html"))

http.HandleFunc("/tools.html", redirHandler("/creations.html")) http.HandleFunc("/projects.html", redirHandler("/creations.html")) - http.HandleFunc("/favicon.ico", faviconHandler) http.HandleFunc("/feeds.html", feedHandler) http.HandleFunc("/feed.atom", atom.Handler) http.HandleFunc("/age.html", ageHandler) http.HandleFunc("/ip.html", ipHandler) - http.HandleFunc("/review/", postHandler) - http.HandleFunc("/thought/", postHandler) + // TODO: redir to https://abyss.j3s.sh + // http.HandleFunc("/review/", postHandler) + http.HandleFunc("/thought/", thoughtHandler) http.HandleFunc("/", serveRoot) log.Println("listening on :4666 tbh") - err := http.ListenAndServe(":4666", nil) + err = http.ListenAndServe(":4666", nil) if err != nil { log.Fatal(err) } } -// templatesCombobulator takes a template & lays it on top -// of the layout template, then passes it back to the user -// this thing also sprinkles on some x-tra necessary funcs -func templateCombobulator(requestedPath string) (template.Template, error) { - layoutPath := filepath.Join("templates", "layout.html") - - _, err := os.Stat(requestedPath) - if err != nil { - return template.Template{}, err - } +// renderPage renders the given page and passes data to the +// template execution engine. it's normally the last thing a +// handler should do tbh. +// +// pass a struct in data & it will be available in your page +// via ".Data" +func renderPage(w http.ResponseWriter, r *http.Request, page string, data any) { + // sanitizing some sheet + page = filepath.Clean(page) + page = strings.TrimPrefix(page, "/") funcMap := template.FuncMap{ "toLower": strings.ToLower,

@@ -114,129 +122,103 @@ "randomheaderphrase": randomJesPhrase,

"randomrotationdegrees": randomRotationDegrees, } - tmpl, err := template.New("unimportant").Funcs(funcMap).ParseFiles(layoutPath, requestedPath) - if err != nil { - return *tmpl, err - } - return *tmpl, nil -} - -func serveRoot(w http.ResponseWriter, r *http.Request) { - if r.URL.Path == "/" { - r.URL.Path = "index.html" - } - requestedPath := filepath.Join("templates", filepath.Clean(r.URL.Path)) - - tmpl, err := templateCombobulator(requestedPath) + tmpl, err := template.New("").Funcs(funcMap).ParseFS(templateFiles, "templates/*.html") if err != nil { - log.Println(err.Error()) - http.Error(w, http.StatusText(404), 404) + log.Println(err) + http.Error(w, err.Error(), 500) return } - err = tmpl.ExecuteTemplate(w, "layout", data) - if err != nil { - log.Println(err.Error()) - http.Error(w, http.StatusText(500), 500) - } -} - -func postHandler(w http.ResponseWriter, r *http.Request) { - lp := filepath.Join("templates", "simple-layout.html") - fp := filepath.Join(strings.TrimPrefix(filepath.Clean(r.URL.Path), "/")) - - info, err := os.Stat(fp) - if err != nil { - if os.IsNotExist(err) { - http.NotFound(w, r) - return - } - } - - if info.IsDir() { + if tmpl.Lookup(page) == nil { http.NotFound(w, r) return } - content, err := os.ReadFile(fp) - if err != nil { - log.Println(err.Error()) - http.Error(w, http.StatusText(500), 500) - return + pageData := struct { + Title string + Data any + }{ + Data: data, } - tmpl, err := template.ParseFiles(lp) + err = tmpl.ExecuteTemplate(w, page, pageData) if err != nil { - log.Println(err.Error()) - http.Error(w, http.StatusText(500), 500) + log.Println(err) + http.Error(w, err.Error(), 500) return } +} - err = tmpl.ExecuteTemplate(w, "simple-layout", string(content)) - if err != nil { - log.Println(err.Error()) - http.Error(w, http.StatusText(500), 500) +func serveRoot(w http.ResponseWriter, r *http.Request) { + if r.URL.Path == "/" { + r.URL.Path = "index.html" } -} -type AgeForm struct { - Success bool - PublicKey string - Message string + renderPage(w, r, r.URL.Path, nil) } -func ageHandler(w http.ResponseWriter, r *http.Request) { - tmpl, err := templateCombobulator(filepath.Join("templates", "age.html")) +func thoughtHandler(w http.ResponseWriter, r *http.Request) { + content, err := fs.ReadFile(thoughtFiles, strings.TrimPrefix(r.URL.Path, "/")) if err != nil { - log.Println(err.Error()) - http.Error(w, http.StatusText(500), 500) + log.Println(err) + if os.IsNotExist(err) { + http.NotFound(w, r) + } else { + http.Error(w, err.Error(), 500) + } return } - if r.Method != http.MethodPost { - tmpl.ExecuteTemplate(w, "layout", nil) - return - } + log.Println(string(content)) + renderPage(w, r, "thought.html", string(content)) +} - formdeets := AgeForm{ - PublicKey: r.FormValue("pubkey"), - Message: r.FormValue("message"), +func ageHandler(w http.ResponseWriter, r *http.Request) { + if r.Method == "GET" { + renderPage(w, r, "age.html", nil) } + if r.Method == "POST" { + type AgeForm struct { + Success bool + PublicKey string + Message string + } + formdeets := AgeForm{ + PublicKey: r.FormValue("pubkey"), + Message: r.FormValue("message"), + } - recipient, err := age.ParseX25519Recipient(formdeets.PublicKey) - if err != nil { - log.Println(err.Error()) - http.Error(w, http.StatusText(500), 500) - return - } + recipient, err := age.ParseX25519Recipient(formdeets.PublicKey) + if err != nil { + log.Println(err.Error()) + http.Error(w, http.StatusText(500), 500) + return + } - buf := &bytes.Buffer{} - armorWriter := armor.NewWriter(buf) + buf := &bytes.Buffer{} + armorWriter := armor.NewWriter(buf) - write, err := age.Encrypt(armorWriter, recipient) - if err != nil { - log.Println(err.Error()) - http.Error(w, http.StatusText(500), 500) - return - } - if _, err := io.WriteString(write, formdeets.Message); err != nil { - log.Println(err.Error()) - http.Error(w, http.StatusText(500), 500) - return - } - if err := write.Close(); err != nil { - log.Println(err.Error()) - http.Error(w, http.StatusText(500), 500) - return - } - if err := armorWriter.Close(); err != nil { - log.Fatalf("Failed to close armor: %v", err) - } + write, err := age.Encrypt(armorWriter, recipient) + if err != nil { + log.Println(err.Error()) + http.Error(w, http.StatusText(500), 500) + return + } + if _, err := io.WriteString(write, formdeets.Message); err != nil { + log.Println(err.Error()) + http.Error(w, http.StatusText(500), 500) + return + } + if err := write.Close(); err != nil { + log.Println(err.Error()) + http.Error(w, http.StatusText(500), 500) + return + } + if err := armorWriter.Close(); err != nil { + log.Fatalf("Failed to close armor: %v", err) + } - err = tmpl.ExecuteTemplate(w, "layout", buf.String()) - if err != nil { - log.Println(err.Error()) - http.Error(w, http.StatusText(500), 500) + renderPage(w, r, "age", buf.String()) } }

@@ -264,7 +246,6 @@ <p> j3s's feeds have moved to <a href="https://vore.website/j3s">vore.website</a>`)

} func randomRotationDegrees() int { - rand.Seed(time.Now().UnixNano()) return rand.Intn(500 - -500) + -500 }
M static/style.cssstatic/style.css

@@ -8,6 +8,10 @@ /* make sure the scrollbar is always shown so

the width doesnt change between pages */ html { overflow-y: scroll + -moz-filter: grayscale(100%); + -webkit-filter: grayscale(100%); + filter: gray; /* IE6-9 */ + filter: grayscale(100%); } img {
M templates/404.htmltemplates/404.html

@@ -1,4 +1,3 @@

-{{define "title"}}not found x__x{{end}} {{define "body"}} <pre> (◎_◎;) 404 not found
M templates/about.htmltemplates/about.html

@@ -1,5 +1,7 @@

-{{define "title"}}about{{end}} -{{define "body"}} +{{ define "about.html" }} +{{ template "head" . }} +{{ template "nav" . }} +<div id="main"> <h3>about</h3> <img src="/static/scrombles.png" width="140" alt="pic of a one eyed cat named scrombles"> <pre>

@@ -64,4 +66,5 @@ <li>to release patterns</li>

<li>or maintenance</li> <li>or fixes</li> <li>or support</li> +</div> {{end}}
M templates/age.htmltemplates/age.html

@@ -1,4 +1,3 @@

-{{define "title"}}tools/age{{end}} {{ define "body" }} <h3>tools/age</h3> <p>use this form to encrypt age data for people, if you want. my public key is <pre>age12amwzaps3lfy5y7kup5h730d2alfcpxlrnahgxv7u4a877hl9c8s6h2wuf</pre></p>

@@ -15,4 +14,4 @@ <pre>

{{ . }} </pre> {{ end }} -{{ end }}+{{ end }}
M templates/creations.htmltemplates/creations.html

@@ -1,5 +1,7 @@

-{{define "title"}}creations{{end}} -{{define "body"}} +{{ define "creations.html" }} +{{ template "head" . }} +{{ template "nav" . }} +<div id="main"> <h3>creations</h3> this page is a showcase for my many creations :3

@@ -34,5 +36,5 @@ <h4>important quotes about me</h4>

<ul><i>the author's projects seem to have a consistent scatalogical theme -some hackernews user</i></ul> <ul><i>very cute j3s style as always i love the lil ascii snail art -aynish</i></ul> <ul><i>so energetic now!! love ya jes :3 -ckie</i></ul> - +</div> {{end}}
A templates/head.html

@@ -0,0 +1,30 @@

+{{ define "head" }} +<!doctype html> +<html> +<head> + <style> + @keyframes lol { + from{ + transform: rotate(0deg); + } + to { + transform: rotate(9000deg); + } + } + + #header img { + animation: lol; + animation-duration: 500s; + animation-timing-function: ease; + animation-fill-mode: forwards; + animation-delay: 1s; + } + </style> + <link rel="stylesheet" href="/static/style.css" type="text/css"> + <link rel='shortcut icon' href='/static/favicon.ico'> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>j3s.sh</title> + <link rel="alternate" title="Sitewide Atom feed" type="application/atom+xml" href="/feed.atom" /> +</head> +{{ end }}
M templates/index.htmltemplates/index.html

@@ -1,8 +1,13 @@

-{{- define "title" }}j3s.sh{{- end }} -{{- define "body" }} +{{ define "index.html" }} +{{ template "head" . }} +{{ template "nav" . }} +<div id="main"> + <p>welcome, internet stranger <p>please get comfy and stay awhile :3 + +<p>also, excuse any weirdness on my site, i just rewrote the backend and some things are wonky. <p> -> scrolling skullz

@@ -10,12 +15,14 @@ <marquee><pre>

*whispers* hello friend hack the planet! 🌎 🐡 it's a unix system. i know this. we're all pilgrims and strangers, and nobody knows what the fuck they're doing. never feel certain. sureness is sin. feel good. pride. confidence. effortless. present. feel bad. doubt. anxiety. potential. past. it's you. it's us. we'll make it. of course. we all must make it. because someday it'll be over. like a great big dream. i hope we can wake up together. and laugh at our efforts completely gone. and gaze into each others eyes for eternity. i want so badly to see you again. 💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀💀 </pre></marquee> +<!-- TODO: re-scope the feed lister <p> -> posts from my friends -{{- range $feed := .Feeds }} +{- range $feed := .Feeds } <li> -<a href="{{ (index .Items 0).Link }}">{{ (index .Items 0).Title }}</a> +<a href="{ (index .Items 0).Link }">{ (index .Items 0).Title }</a> </li> -{{- end }} +{- end } +--> <p> -> quote/poem selection <details> <summary>when you need hope and feel lost</summary>

@@ -89,6 +96,5 @@ <br>

<a title="Previous site" href="https://cyberia.click/prev.cgi?source=jes" class="no-underline"><-</a> <a href="https://cyberia.click" class="no-underline icon" title="cyberia webring">cyberia webring</a> <a title="Next site" href="https://cyberia.click/next.cgi?source=jes" class="no-underline">-></a> - - -{{- end }} +</div> +{{ end }}
M templates/layout.htmltemplates/layout.html

@@ -1,50 +1,5 @@

{{ define "layout" }} -<!doctype html> -<html> -<head> - <style> - @keyframes lol { - from{ - transform: rotate(0deg); - } - to { - transform: rotate(9000deg); - } - } - - #header img { - animation: lol; - animation-duration: 500s; - animation-timing-function: ease; - animation-fill-mode: forwards; - animation-delay: 1s; - } - </style> - <link rel="stylesheet" href="/static/style.css" type="text/css"> - <meta charset="utf-8"> - <meta name="viewport" content="width=device-width, initial-scale=1.0"> - <title>{{template "title"}}</title> - <link rel="alternate" title="Sitewide Atom feed" type="application/atom+xml" href="/feed.atom" /> -</head> - -<body class="grayscale"> - <div id="header"> - <a href="/"><img src="/static/unnamed-puffy.png" height="111" width="140" alt="pic of an unnamed pufferfish, drawn by rekka bellum of kokorobot.ca and hundred rabbits :3"></a> - <h2>jes {{ randomheaderphrase }}</h2> - <p> - <a href="/now.html">now</a> - <a href="/about.html">about</a> - <a href="/thoughts.html">thoughts</a> - <a href="/creations.html">creations</a> - <a href="https://git.j3s.sh">git</a> - <a class="abyss" href="https://abyss.j3s.sh">abyss</a> - </p> - <hr> - </div> - <div id="main"> - {{ template "body" . }} - </div> -</body> - -</html> +<div id="main"> + {{ template "body" . }} +</div> {{ end }}
A templates/nav.html

@@ -0,0 +1,17 @@

+{{ define "nav" }} +<div id="header"> + <a href="/"> + <img src="/static/unnamed-puffy.png" height="111" width="140" alt="pic of an unnamed pufferfish, drawn by rekka bellum of kokorobot.ca and hundred rabbits :3"> + </a> + <h2>jes {{ randomheaderphrase }}</h2> + <p> + <a href="/now.html">now</a> + <a href="/about.html">about</a> + <a href="/thoughts.html">thoughts</a> + <a href="/creations.html">creations</a> + <a href="https://git.j3s.sh">git</a> + <a class="abyss" href="https://abyss.j3s.sh">abyss</a> + </p> + <hr> +</div> +{{ end }}
M templates/now.htmltemplates/now.html

@@ -1,5 +1,7 @@

-{{define "title"}}now{{end}} -{{define "body"}} +{{ define "now.html" }} +{{ template "head" . }} +{{ template "nav" . }} +<div id="main"> <h3>now</h3> <p>this page descibes what i'm up to _now_</p> <h4>books</h4>

@@ -102,4 +104,5 @@ <li>developing a fully libre version of <a href="https://capsul.org">capsul</a></li>

<li>made jrss - my feed is <a href="/feeds">here</a></li> <li>set up a ci/cd system for cyberia <a href="https://builds.cyberia.club">linky</a></li> <li>moved in with some of my very good friends</li> +</div> {{end}}
M templates/reviews.htmltemplates/reviews.html

@@ -1,4 +1,3 @@

-{{define "title"}}reviews{{end}} {{define "body"}} <h3>reviews</h3> <p><i>this is where i review movies, tech stuff, lotion, etc</p></i>
M templates/simple-layout.htmltemplates/thought.html

@@ -1,4 +1,4 @@

-{{define "simple-layout"}} +{{define "thought.html"}} <!doctype html> <html> <head>

@@ -11,6 +11,7 @@ </style>

<meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <link rel='shortcut icon' href='/static/favicon.ico'> <title>jes post</title> </head> <div id="main"><body class="grayscale">

@@ -18,7 +19,7 @@ <a href="/"><img height="92" src="/static/unnamed-puffy.png" alt="another pufferfish drawn by rekka"></a>

<a href="/"><img height="92" src="/static/unnamed-puffy-2.png" alt="yet another pufferfish drawn by rekka"></a> <a href="/"><img height="92" src="/static/unnamed-puffy-3.png" alt="yet another pufferfish drawn by rekka"></a> <hr> - <pre>{{ . }}</pre> + <pre>{{ .Data }}</pre> </div></body> </html> {{end}}
M templates/thoughts.htmltemplates/thoughts.html

@@ -1,5 +1,7 @@

-{{define "title"}}j3s thoughts{{end}} -{{define "body"}} +{{ define "thoughts.html" }} +{{ template "head" . }} +{{ template "nav" . }} +<div id="main"> <p><i><a href="/feed.atom">rss feed</a></i></p> <p><i>ever wanted to peer into the head of a MANIAC?</p></i> <h4>2023</h4>

@@ -29,4 +31,5 @@ <li><a href="/thought/pumpernickel-bread.html">pumpernickel-bread</a></li>

<li><a href="/thought/something-is-different.html">something-is-different</a></li> <hr> <img src="/static/thoughtscrombles.png" alt="scrombles the cat"> +</div> {{end}}
M templates/travel.htmltemplates/travel.html

@@ -1,4 +1,3 @@

-{{define "title"}}tools/travel{{end}} {{define "body"}} <p>this is my travel checklist. you can use it too if you want i guess.</p> <h4>clothes</h4>