funny sidebart
This commit is contained in:
parent
0bd0cd2f25
commit
5726b1d74d
124
caddy/Caddyfile
124
caddy/Caddyfile
|
@ -1,11 +1,20 @@
|
|||
(respond_file) {
|
||||
root * {args[0]}
|
||||
try_files {args[1:]}
|
||||
file_server
|
||||
}
|
||||
|
||||
zvava.org {
|
||||
# discrimination
|
||||
@brave {
|
||||
header_regexp Sec-Ch-Ua "(?i)(Brave)"
|
||||
header_regexp Cookie "(?i)(Brave-User)"
|
||||
}
|
||||
respond @brave "you are not brave enough" 400
|
||||
|
||||
@operagx header_regexp Sec-Ch-Ua "(?i)(opera gx)"
|
||||
respond @operagx "gamers not allowed" 400
|
||||
|
||||
@brave header_regexp Cookie "(?i)(Brave-User)"
|
||||
respond @brave "you are not brave enough" 400
|
||||
|
||||
# media
|
||||
@media path /media /media/*
|
||||
route @media {
|
||||
|
@ -18,27 +27,41 @@ zvava.org {
|
|||
}
|
||||
}
|
||||
|
||||
# api
|
||||
@schema path /schema /schema/ /api/jsonld /api/jsonld/
|
||||
@api path /api /api/
|
||||
@viewcount path /api/viewcount /api/viewcount/ /api/viewcount/*
|
||||
@hue path /api/hue /api/hue/ /api/hue/*
|
||||
@ntfy path /api/ntfy /api/ntfy/
|
||||
@sophia path /api/sophia /api/sophia/
|
||||
respond @api `["jsonld", "viewcount", "hue", "ntfy", "sophia"]`
|
||||
# jsonld
|
||||
handle @schema {
|
||||
header Content-Type "application/ld+json"
|
||||
import respond_file /var/lib/syncthing/zvava.org.media/misc /schema.jsonld
|
||||
}
|
||||
# api endpoints
|
||||
reverse_proxy @viewcount localhost:8001
|
||||
reverse_proxy @hue localhost:8003
|
||||
handle @ntfy {
|
||||
import respond_file /etc/caddy /api.ntfy.txt
|
||||
}
|
||||
handle @sophia {
|
||||
redir https://zvava.org/schema permanent
|
||||
}
|
||||
|
||||
# wiki
|
||||
root * /var/www
|
||||
file_server
|
||||
|
||||
# firefox fix
|
||||
rewrite /favicon.ico /images/favicon.ico
|
||||
# inline files fix
|
||||
@inline path *.ass *.bat *.txt
|
||||
@inline path *.ass *.bat *.txt *.pub *.asc
|
||||
header @inline {
|
||||
Content-Type text/plain
|
||||
Content-Disposition inline
|
||||
}
|
||||
|
||||
# api
|
||||
@api path /api /api/
|
||||
@viewcount path /api/viewcount /api/viewcount/*
|
||||
@ntfy path /api/ntfy /api/ntfy/*
|
||||
reverse_proxy @viewcount localhost:8001
|
||||
reverse_proxy @ntfy localhost:8002
|
||||
respond @api `["viewcount", "ntfy"]`
|
||||
|
||||
handle_errors {
|
||||
handle /api/* {
|
||||
header Content-Type application/json
|
||||
|
@ -57,19 +80,88 @@ zvava.org {
|
|||
respond "{err.status_code} — {err.status_text}"
|
||||
}
|
||||
}
|
||||
|
||||
file_server
|
||||
}
|
||||
|
||||
http://www.zvava.org, www.zvava.org {
|
||||
redir https://zvava.org{uri} permanent
|
||||
}
|
||||
|
||||
### robogirl site ###
|
||||
737a6f6669e1.id {
|
||||
header Content-Type application/ld+json
|
||||
header Content-Disposition inline
|
||||
@mobile header_regexp User-Agent (?i)(mobile|android)
|
||||
header @mobile Content-Type text/plain
|
||||
import respond_file /var/lib/syncthing/zvava.org.media /737A6F6669E1.jsonld
|
||||
}
|
||||
|
||||
http://www.737a6f6669e1.id, www.737a6f6669e1.id {
|
||||
redir https://737a6f6669e1.id{uri} permanent
|
||||
}
|
||||
|
||||
### programming language site ###
|
||||
magenta.zvava.org {
|
||||
root * /var/magenta.www
|
||||
file_server
|
||||
|
||||
handle_errors {
|
||||
@404 expression {err.status_code} == 404
|
||||
rewrite @404 /404.html
|
||||
file_server
|
||||
}
|
||||
|
||||
file_server
|
||||
}
|
||||
|
||||
### ntfy server ###
|
||||
ntfy.zvava.org, http://nfty.zvava.org {
|
||||
reverse_proxy localhost:8002
|
||||
|
||||
@httpget {
|
||||
protocol http
|
||||
method GET
|
||||
path_regexp ^/([-_a-z0-9]{0,64}$|docs/|static/)
|
||||
}
|
||||
redir @httpget https://{host}{uri}
|
||||
@websockets {
|
||||
header Connection *Upgrade*
|
||||
header Upgrade websocket
|
||||
}
|
||||
reverse_proxy @websockets localhost:8002 {
|
||||
header_up Host {host}
|
||||
header_up X-Real-IP {remote_host}
|
||||
header_up X-Forwarded-For {remote_host}
|
||||
header_up X-Forwarded-Proto {scheme}
|
||||
}
|
||||
}
|
||||
|
||||
### git forgejo ###
|
||||
git.zvava.org {
|
||||
reverse_proxy * localhost:8080
|
||||
reverse_proxy localhost:8080
|
||||
}
|
||||
|
||||
### firefish ###
|
||||
fish.zvava.org {
|
||||
reverse_proxy localhost:8080
|
||||
}
|
||||
|
||||
### personal server 1 ###
|
||||
isopropyl.zvava.org {
|
||||
reverse_proxy localhost:8080
|
||||
}
|
||||
|
||||
### personal server 2 ###
|
||||
hierophant.zvava.org {
|
||||
reverse_proxy localhost:8080
|
||||
}
|
||||
|
||||
### personal server 3 ###
|
||||
zerov.zvava.org {
|
||||
reverse_proxy localhost:8080
|
||||
}
|
||||
|
||||
### ofical magyar smosh ###
|
||||
http://www.smosh.hu/, http://smosh.hu, www.smosh.hu, smosh.hu {
|
||||
root * /var/smosh.hu.www
|
||||
file_server
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
✉️
|
||||
{{- else if .HasExt ".crt" ".pem" ".x509" ".cer" ".ca-bundle"}}
|
||||
🧾
|
||||
{{- else if .HasExt ".key" ".keystore" ".jks" ".p12" ".pfx" ".pub"}}
|
||||
{{- else if .HasExt ".key" ".keystore" ".jks" ".p12" ".pfx" ".pub" ".asc"}}
|
||||
🔑
|
||||
{{- else}}
|
||||
📄
|
||||
|
@ -102,7 +102,7 @@ a[href]:hover, a[href]:focus {
|
|||
<hr>
|
||||
<div class="entry">
|
||||
<span class="date"></span>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
|
169
make.js
169
make.js
|
@ -201,6 +201,14 @@ function generateTemplates() {
|
|||
+ "\n```\n " + `[${p.modified}] [${category}]` + "\n```"
|
||||
}).join("\n") // stringify
|
||||
|
||||
// → {html_wiki_recent} template
|
||||
// remove stubs, get first five pages, and render template
|
||||
templates["html_wiki_recent"] = pages.filter(page => !page.category.includes("stub")).slice(0, 5).map((p, i) => {
|
||||
let category = prependRelevantEmoji(p.category[0]).split(" ")[0] // get category emoji
|
||||
// render
|
||||
return `<a class="sidebar__link" href="/wiki/${p.page}.html">${category} ${p.title}<br><pre> ${p.modified}</pre></a>`
|
||||
}).join("\n") // stringify
|
||||
|
||||
// → {wiki_all} template
|
||||
// remove stubs and render template
|
||||
templates["wiki_all"] = pages.filter(page => !page.category.includes("stub")).map(p => {
|
||||
|
@ -232,6 +240,14 @@ function generateTemplates() {
|
|||
templates["wiki_category__" + c] = catMeta + catBody + "\n" + ps.join("\n\n")
|
||||
})
|
||||
|
||||
// → {wiki_pinned} and {html_wiki_pinned}
|
||||
templates["wiki_pinned"] = templates["pinned-pages.gmi"]
|
||||
templates["html_wiki_pinned"] = parseGemini("", templates["wiki_pinned"]).replace(/<p>|<\/p>|<br>/g, "")
|
||||
.replace(/<a/g, "<a class=\"sidebar__link\"")
|
||||
|
||||
// → {head.html} template
|
||||
templates["head.html"] = useTemplate("head.html", [ "html_wiki_pinned", "html_wiki_recent" ])
|
||||
|
||||
// → {html_filter} template
|
||||
templates["html_filter__inputs"] = '<input type="radio" name="category" id="all" checked>\n' +
|
||||
ctgs.filter(x => x != "stub").map(x => `<input type="radio" name="category" id="${x}">`).join("\n")
|
||||
|
@ -278,7 +294,7 @@ function generateGemini() {
|
|||
|
||||
// use templates
|
||||
// → index
|
||||
files["index"] = useTemplate("index.gmi", [ "wiki_recent", "build_info_summary" ])
|
||||
files["index"] = useTemplate("index.gmi", [ "wiki_recent", "build_info_summary", "wiki_pinned" ])
|
||||
// → stats
|
||||
files["stats"] = useTemplate("stats.gmi", [ "build_info" ])
|
||||
|
||||
|
@ -341,80 +357,23 @@ function generateHTML(files) {
|
|||
let output = templates["head.html"].replace("{title}", title)
|
||||
if (isCategoryPage) output = output.replace("<div class=\"wrap\">", `<div class="wrap wrap__category">`)
|
||||
|
||||
let _c = files[f]
|
||||
.replace(/{gmi[a-z_]*}\n/g, "") // remove gmi-only templates
|
||||
.replace(/\.ln/g, ".html") // replace ambiguous links
|
||||
.replace(/stay:\/\//g, "https://") // replace ambiguous protocols
|
||||
.split("\n```\n") // split into variable for optimized access to .length
|
||||
_c.forEach((x, i) => {
|
||||
// if file contains a code block and you are currently in one
|
||||
if (_c.length > 1 && i % 2 !== 0)
|
||||
return output += x + "</pre>\n"
|
||||
output = parseGemini(output, files[f], (l) => {
|
||||
if (f == "index" && /href="https:\/\/(mk\.catgirlsfor\.science|git\.zvava\.org|www\.buymeacoffee\.com|matrix\.to)/.test(l))
|
||||
l = l.replace(">", " rel=\"me\">") // add rel=me attribute to some links
|
||||
|
||||
// parse remaining content
|
||||
output += x.split(/\n/).map((l, i, a) => {
|
||||
l = l.replace(/</g, "<") // escape html tag opening brackets
|
||||
.replace(/^({br}|>)$/i, "<br>") // add line breaks
|
||||
// convert headers
|
||||
.replace(/^### +(.*)/, "<h3>$1</h3>")
|
||||
.replace(/^## +(.*)/, "<h2>$1</h2>")
|
||||
.replace(/^# +(.*)/, "<h1>$1</h1>")
|
||||
// convert images
|
||||
.replace(/^=> +([a-z0-9\-_\/\.\(\),+:@?!&=#~']+)\.(png|jpg) +(.*)/i, '<img src="$1.$2" alt="$3" title="$3">')
|
||||
.replace(/^=> +([a-z0-9\-_\/\.\(\),+:@?!&=#~']+)\.(png|jpg)/i, '<img src="$1.$2">')
|
||||
// convert audio
|
||||
.replace(/^=> +([a-z0-9\-_\/\.\(\),+:@?!&=#~']+)\.mp3 *(.*)/i,
|
||||
'<audio controls><source src="$1.mp3" type="audio/mpeg">🔈 audio</audio>')
|
||||
// convert video
|
||||
.replace(/^=> +([a-z0-9\-_\/\.\(\),+:@?!&=#~']+)\.mp4 *(.*)/i,
|
||||
'<video controls><source src="$1.mp4" type="video/mp4">📼 video</video>')
|
||||
// convert links
|
||||
.replace(/^=> +([a-z0-9\-_\/\.\(\)%,+:@?!&=#~']+) +(.*)/i, '<a href="$1">$2</a>')
|
||||
.replace(/^=> +([a-z0-9\-_\/\.\(\)%,+:@?!&=#~']+)/i, '<a href="$1">$1</a>')
|
||||
// convert block quotes
|
||||
.replace(/^> *(.*)/, "<blockquote>$1</blockquote>")
|
||||
// convert lists
|
||||
.replace(/^[-*+] +(.*)/, "<span class=\"ui\">$1</span>")
|
||||
.replace(/^([0-9a-bA-B\.]+)\. +(.*)/, "<span class=\"oi\" data-i=\"$1\">$2</span>")
|
||||
if (f == "wiki/index" && /<a href="\/wiki\/(?!category).+"/.test(l)) { // to append data-category attribute for filters
|
||||
let start = l.indexOf("/wiki/") + 6, end = l.indexOf(".html", start)
|
||||
let page = pages.find(x => x.page == l.substring(start, end)) // get linked page
|
||||
l = l.replace(">", ` data-category="${page ? page.category.join(" ") : "⚠️"}">`) // add
|
||||
}
|
||||
|
||||
if (f == "index" && /href="https:\/\/(mk\.catgirlsfor\.science|git\.zvava\.org|www\.buymeacoffee\.com|matrix\.to)/.test(l))
|
||||
l = l.replace(">", "rel=\"me\">") // add rel=me attribute to some links
|
||||
|
||||
if (f == "wiki/index" && /<a href="\/wiki\/(?!category).+"/.test(l)) { // to append data-category attribute for filters
|
||||
let start = l.indexOf("/wiki/") + 6, end = l.indexOf(".html", start)
|
||||
let page = pages.find(x => x.page == l.substring(start, end)) // get linked page
|
||||
l = l.replace(">", ` data-category="${page ? page.category.join(" ") : "⚠️"}">`) // add
|
||||
}
|
||||
|
||||
// will this line be considered for its spacing?
|
||||
if (!l.startsWith("<h") && !l.startsWith("<b") && l.replace(/\n/g, "").length > 0) {
|
||||
// fetch previous/next lines (default to empty string if not able to acquire)
|
||||
let previousLine = (a[i - 1] || ""); let nextLine = (a[i + 1] || "")
|
||||
// check if previous/next line is empty or contains a heading or blockquote
|
||||
let pLineEmpty = previousLine.length == 0 || previousLine.startsWith("#") || previousLine.startsWith(">")
|
||||
let nLineEmpty = nextLine.length == 0 || nextLine.startsWith("#") || nextLine.startsWith(">")
|
||||
|
||||
if (pLineEmpty && nLineEmpty) // 0 & 0
|
||||
l = "<p>" + l + "</p>" // single lonely paragraph
|
||||
else if (pLineEmpty && !nLineEmpty) // 0 & 1
|
||||
l = "<p>" + l + "<br>" // start a paragraph with line breaks
|
||||
else if (!pLineEmpty && nLineEmpty) // 1 & 0
|
||||
l = l + "</p>" // end a paragraph with line breaks
|
||||
else if (!pLineEmpty && !nLineEmpty) // 1 & 1
|
||||
l += "<br>" // end a line in a paragraph with a line break
|
||||
}
|
||||
|
||||
return l
|
||||
}) // remove empty sections and join into one
|
||||
.filter(x => x.length > 0).join("\n") + "\n"
|
||||
|
||||
// if file contains a code block and you _just_ aren't at the end of file
|
||||
if (_c.length > 1 && i != _c.length - 1) output += "<pre>"
|
||||
return l
|
||||
})
|
||||
|
||||
if (f == "index") { // home page
|
||||
output = output.replace("{html_buttons}", templates["html_buttons"]) // buttons!!
|
||||
.replace("{html_webrings}", templates["webrings.html"]) // fancy webrings
|
||||
.replace("{html_color}", templates["color.html"]) // hue-server client
|
||||
// add viewcounter script that doesn't display the count
|
||||
+ templates["viewcounter.html"].replace("{url}", "/" + f + ".html")
|
||||
} else if (f == "stats") { // statistics page
|
||||
|
@ -433,6 +392,10 @@ function generateHTML(files) {
|
|||
.replace("{url}", "/" + f + ".html")
|
||||
}
|
||||
|
||||
output = output
|
||||
.replace(/{html_sbcont_start}(<br>)?/g, "<div class=\"sidebar-content\">")
|
||||
.replace(/{html_sbcont_end}(<br>)?/g, "</div>")
|
||||
|
||||
let _f = std.open("out/www/" + f + ".html", "w")
|
||||
if (_f.error()) reject(_f.error())
|
||||
_f.puts(output + "</div></body>\n</html>\n")
|
||||
|
@ -464,3 +427,73 @@ function generateAss() {
|
|||
|
||||
print("\r\x1b[32m-->\x1b[0m finished make script")
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
function parseGemini(_output, file, hooks = (l) => l) {
|
||||
let output = _output
|
||||
let _c = file
|
||||
.replace(/{gmi[a-z_]*}\n/g, "") // remove gmi-only templates
|
||||
.replace(/\.ln/g, ".html") // replace ambiguous links
|
||||
.replace(/stay:\/\//g, "https://") // replace ambiguous protocols
|
||||
.split("\n```\n") // split into variable for optimized access to .length
|
||||
_c.forEach((x, i) => {
|
||||
// if file contains a code block and you are currently in one
|
||||
if (_c.length > 1 && i % 2 !== 0)
|
||||
return output += x + "</pre>\n"
|
||||
|
||||
// parse remaining content
|
||||
output += x.split(/\n/).map((l, i, a) => {
|
||||
l = l.replace(/</g, "<") // escape html tag opening brackets
|
||||
.replace(/^({br}|>)$/i, "<br>") // add line breaks
|
||||
// convert headers
|
||||
.replace(/^### +(.*)/, "<h3>$1</h3>")
|
||||
.replace(/^## +(.*)/, "<h2>$1</h2>")
|
||||
.replace(/^# +(.*)/, "<h1>$1</h1>")
|
||||
// convert images
|
||||
.replace(/^=> +([a-z0-9\-_\/\.\(\),+:@?!&=#~']+)\.(png|jpg) +(.*)/i, '<img src="$1.$2" alt="$3" title="$3">')
|
||||
.replace(/^=> +([a-z0-9\-_\/\.\(\),+:@?!&=#~']+)\.(png|jpg)/i, '<img src="$1.$2">')
|
||||
// convert audio
|
||||
.replace(/^=> +([a-z0-9\-_\/\.\(\),+:@?!&=#~']+)\.mp3 *(.*)/i,
|
||||
'<audio controls><source src="$1.mp3" type="audio/mpeg">🔈 audio</audio>')
|
||||
// convert video
|
||||
.replace(/^=> +([a-z0-9\-_\/\.\(\),+:@?!&=#~']+)\.mp4 *(.*)/i,
|
||||
'<video controls><source src="$1.mp4" type="video/mp4">📼 video</video>')
|
||||
// convert links
|
||||
.replace(/^=> +([a-z0-9\-_\/\.\(\)%,+:@?!&=#~']+) +(.*)/i, '<a href="$1">$2</a>')
|
||||
.replace(/^=> +([a-z0-9\-_\/\.\(\)%,+:@?!&=#~']+)/i, '<a href="$1">$1</a>')
|
||||
// convert block quotes
|
||||
.replace(/^> *(.*)/, "<blockquote>$1</blockquote>")
|
||||
// convert lists
|
||||
.replace(/^[-*+] +(.*)/, "<span class=\"ui\">$1</span>")
|
||||
.replace(/^([0-9a-bA-B\.]+)\. +(.*)/, "<span class=\"oi\" data-i=\"$1\">$2</span>")
|
||||
|
||||
l = hooks(l)
|
||||
|
||||
// will this line be considered for its spacing?
|
||||
if (!l.startsWith("<h") && !l.startsWith("<b") && l.replace(/\n/g, "").length > 0) {
|
||||
// fetch previous/next lines (default to empty string if not able to acquire)
|
||||
let previousLine = (a[i - 1] || ""); let nextLine = (a[i + 1] || "")
|
||||
// check if previous/next line is empty or contains a heading or blockquote
|
||||
let pLineEmpty = previousLine.length == 0 || previousLine.startsWith("#") || previousLine.startsWith(">")
|
||||
let nLineEmpty = nextLine.length == 0 || nextLine.startsWith("#") || nextLine.startsWith(">")
|
||||
|
||||
if (pLineEmpty && nLineEmpty) // 0 & 0
|
||||
l = "<p>" + l + "</p>" // single lonely paragraph
|
||||
else if (pLineEmpty && !nLineEmpty) // 0 & 1
|
||||
l = "<p>" + l + "<br>" // start a paragraph with line breaks
|
||||
else if (!pLineEmpty && nLineEmpty) // 1 & 0
|
||||
l = l + "</p>" // end a paragraph with line breaks
|
||||
else if (!pLineEmpty && !nLineEmpty) // 1 & 1
|
||||
l += "<br>" // end a line in a paragraph with a line break
|
||||
}
|
||||
|
||||
return l
|
||||
}) // remove empty sections and join into one
|
||||
.filter(x => x.length > 0).join("\n") + "\n"
|
||||
|
||||
// if file contains a code block and you _just_ aren't at the end of file
|
||||
if (_c.length > 1 && i != _c.length - 1) output += "<pre>"
|
||||
})
|
||||
return output
|
||||
}
|
||||
|
|
|
@ -11,7 +11,8 @@ else
|
|||
echo "-> running generator script"
|
||||
/usr/local/bin/qjs make.js
|
||||
echo "-> copying files"
|
||||
cp -ru out/gemini/* /var/gemini/content/
|
||||
cp -ru out/www/* /var/www/
|
||||
rsync --recursive --fsync --delete out/gemini/* /var/gemini/content/.
|
||||
rsync --recursive --fsync --delete out/www/* /var/www/.
|
||||
# TODO: update caddy config?
|
||||
echo "-> done!"
|
||||
fi
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 4.5 KiB |
Binary file not shown.
After Width: | Height: | Size: 4.3 KiB |
Binary file not shown.
After Width: | Height: | Size: 122 KiB |
|
@ -1,5 +1,7 @@
|
|||
{html_sbcont_start}
|
||||
=> / 🏡 go home...
|
||||
=> /wiki/ 🗃️ go back...
|
||||
{html_sbcont_end}
|
||||
|
||||
# categories
|
||||
=> /images/t/categories.png thumbnail
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
{html_sbcont_start}
|
||||
=> / 🏡 go home...
|
||||
{html_sbcont_end}
|
||||
=> /wiki/category/ 📚 go back...
|
||||
|
||||
# {category_title}
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
</p>
|
||||
|
||||
<div class="sidebar-content">
|
||||
<span class="webring__title">color of the moment</span>
|
||||
<div class="webring__wrapper" style="height: unset; padding: .6rem 0 0 1.2rem">
|
||||
<iframe style="width: 50%; height: 31px;" src="https://zvava.org/api/hue/client" frameborder="0"></iframe>
|
||||
</div>
|
||||
<div class="webring__wrapper">
|
||||
<a href="/wiki/hue-server.html">powered by hue-server</a> <span style="opacity: .5">((and decided by viewers like yourself!)</span>
|
||||
</div>
|
||||
</div>
|
|
@ -9,4 +9,28 @@
|
|||
<script src="/zvava.js"></script>
|
||||
<title>{title}</title>
|
||||
</head>
|
||||
<body><div class="wrap">
|
||||
<body><nav>
|
||||
<div class="window fake" style="margin-right: -1px">
|
||||
<div class="window-titlebar"><div class="window__title">sophia.jpg</div><div class="window-titlebar__maximize"></div><div class="window-titlebar__close"></div></div>
|
||||
<div style="aspect-ratio: 1 / 1; background: url('/images/sophia.jpg') center / contain" title="sophia's old profile picture tinted green"></div>
|
||||
</div>
|
||||
|
||||
<div class="sidebar-content">
|
||||
<div class="sidebar__header">navigation</div>
|
||||
<a class="sidebar__link" href="/">🏡 home</a>
|
||||
<a class="sidebar__link" href="/wiki/">🗃️ wiki</a>
|
||||
<a class="sidebar__link" href="/wiki/category/">📚 categories</a>
|
||||
<div class="sidebar__header">pinned pages</div>
|
||||
{html_wiki_pinned}
|
||||
<div class="sidebar__header">recently updated</div>
|
||||
{html_wiki_recent}
|
||||
</div>
|
||||
|
||||
<div class="sidebar-bottom">
|
||||
<div class="sidebar__header">a color <a class="nob4" href="/wiki/hue-server.html"><?></a></div>
|
||||
<iframe style="width: 100%; height: 31px; margin-bottom: -6px" src="https://zvava.org/api/hue/client" frameborder="0"></iframe>
|
||||
|
||||
<div class="sidebar__header">link my 88x31 <3</div>
|
||||
<a class="nob4" href="/images/buttons/zvava.org.png"><div style="height: 42px; background: url('/images/buttons/zvava.org.png') center"></div></a>
|
||||
</div>
|
||||
</nav><div class="wrap">
|
||||
|
|
|
@ -1,18 +1,13 @@
|
|||
=> /images/header.png welcome to zvava.org ({build_info_summary})
|
||||
|
||||
hey, i'm sophia (she/her) but u can call me sophie ^-^!! you are currently looking at my brain-out-on-a-table, where i keep a constantly evolving collection of thoughts and projects — the first link takes you to the categories of the articles on here, then there are a few highlight pages. CYBERPUNK IS NOW wawawawa
|
||||
hey, i'm sophia (she/her) but u can call me sophie ^-^!! you are currently looking at my brain-out-on-a-table, where i keep a constantly evolving collection of thoughts and projects — the first link takes you to the categories of the articles on here, then there are a handful of highlight pages. CYBERPUNK IS NOW squeeek i am just a little mouse squeak squeak wawawawa
|
||||
|
||||
{html_sbcont_start}
|
||||
## navigation
|
||||
=> /wiki/category/ 📚 categories
|
||||
=> /wiki/about-sophie.ln 🏌️♀️ about me
|
||||
=> /wiki/favorites.ln ⭐ favorites
|
||||
=> /wiki/category/music.ln 🎶 music
|
||||
=> /wiki/category/video.ln 📼 videos
|
||||
=> /wiki/category/internet.ln 🌐 internet
|
||||
=> /wiki/wren.ln 🐦⬛ wren
|
||||
=> /wiki/config.ln ⚙️ config
|
||||
=> /wiki/category/rainmeter.ln 💧 rainmeter
|
||||
=> /wiki/about-site.ln ❓ about site
|
||||
{wiki_pinned}
|
||||
{html_sbcont_end}
|
||||
{html_color}
|
||||
|
||||
## links
|
||||
=> https://mk.catgirlsfor.science/@zvava 🔮 fediverse
|
||||
|
@ -21,14 +16,13 @@ hey, i'm sophia (she/her) but u can call me sophie ^-^!! you are currently looki
|
|||
=> https://keyoxide.org/5386D9E7ED1C49BEE15B9F32074FE2D02D45891C 🔏 keyoxide
|
||||
=> https://www.buymeacoffee.com/zvavava 🍺 buy me a beer!
|
||||
|
||||
{gmi_webrings}
|
||||
{html_webrings}
|
||||
|
||||
{html_sbcont_start}
|
||||
## wiki
|
||||
=> /wiki/ 🗃️ wiki
|
||||
=> /wiki/category/ 📚 categories
|
||||
=> /stats.ln 📊 statistics
|
||||
{wiki_recent}
|
||||
{html_sbcont_end}
|
||||
|
||||
## contact
|
||||
```
|
||||
|
@ -41,7 +35,9 @@ discord @zvava
|
|||
|
||||
## exit the wiki
|
||||
=> /wiki/gemini-sites.ln 🪐 gemini directory
|
||||
{br}
|
||||
|
||||
{gmi_webrings}
|
||||
{html_webrings}
|
||||
|
||||
```
|
||||
「 the internet is not a big truck
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
=> /wiki/about-sophie.ln 🏌️♀️ about me
|
||||
=> /wiki/favorites.ln ⭐ favorites
|
||||
=> /wiki/category/music.ln 🎶 music
|
||||
=> /wiki/category/video.ln 📼 videos
|
||||
=> /wiki/category/internet.ln 🌐 internet
|
||||
=> /wiki/wren.ln 🐦⬛ wren
|
||||
=> /wiki/config.ln ⚙️ config
|
||||
=> /wiki/category/rainmeter.ln 💧 rainmeter
|
||||
=> /wiki/about-site.ln ❓ about site
|
|
@ -1,3 +1,4 @@
|
|||
### webrings
|
||||
hacker girls~
|
||||
=> https://lunabee.space/ (prev) lunabee
|
||||
=> https://nthia.dev/ (next) synthia
|
||||
|
|
|
@ -1,43 +1,25 @@
|
|||
</p><!-- my own folly -->
|
||||
<span class="webring__title">hacker girls</span>
|
||||
<div class="webring webring__wrapper">
|
||||
<a class="nob4" href="https://lunabee.space/">lunabee ⇐</a>
|
||||
<span style="opacity: .5">soph</span>
|
||||
<a class="nob4" href="https://nthia.dev/">⇒ synthia</a>
|
||||
</div>
|
||||
<div class="webring webring__wrapper">
|
||||
</p>
|
||||
<p style="margin: 1.15rem 0 1.75rem">
|
||||
<span style="color: #c27ed5">⇒</span> hackergirls webring<br>
|
||||
<a style="margin-left: 3.5ch" class="nob4" href="https://lunabee.space/">lunabee ⇐</a> <span style="opacity: .5">soph</span> <a class="nob4" href="https://nthia.dev/">⇒ synthia</a><br>
|
||||
<span style="margin: .5ch 0 1ch 3.5ch" class="webring">
|
||||
<img src="/images/buttons/hackergirls.gif" alt="hackergirls' badge">
|
||||
<img src="/images/buttons/hackergirls2.gif" alt="hackergirls' badge">
|
||||
<img src="/images/buttons/hackergirls3.gif" alt="hackergirls' badge">
|
||||
<span style="opacity: .5">hack the planet!!</span>
|
||||
</div>
|
||||
|
||||
<p></p>
|
||||
|
||||
<span class="webring__title">merveilles</span>
|
||||
<div class="webring webring__wrapper">
|
||||
<a class="nob4 webring" href="https://webring.xxiivv.com/#icons" title="merveilles webring">
|
||||
<svg width="235" height="211" viewBox="0 0 235 211"><title>webring</title><g stroke="currentColor" stroke-width="28" fill="none" fill-rule="evenodd" stroke-linecap="square"><path d="M70.038 166.32c16.569 28.698 53.264 38.53 81.962 21.962 28.698-16.569 38.53-53.264 21.962-81.961l-50-86.603"></path><path d="M173.962 164.68c16.568-28.698 6.736-65.393-21.962-81.962-28.698-16.569-65.393-6.736-81.962 21.961l-50 86.603"></path><path d="M121 75c-33.137 0-60 26.863-60 60s26.863 60 60 60h100"></path></g></svg>
|
||||
<span>webrimg</span>
|
||||
</a>
|
||||
</div>
|
||||
</span>
|
||||
|
||||
<span style="color: #c27ed5">⇒</span> merveilles webring<br>
|
||||
<a style="margin-left: 3.5ch" class="nob4 webring" href="https://webring.xxiivv.com/#icons" title="merveilles webring">
|
||||
<svg width="235" height="211" viewBox="0 0 235 211"><title>webring</title><g stroke="currentColor" stroke-width="28" fill="none" fill-rule="evenodd" stroke-linecap="square"><path d="M70.038 166.32c16.569 28.698 53.264 38.53 81.962 21.962 28.698-16.569 38.53-53.264 21.962-81.961l-50-86.603"></path><path d="M173.962 164.68c16.568-28.698 6.736-65.393-21.962-81.962-28.698-16.569-65.393-6.736-81.962 21.961l-50 86.603"></path><path d="M121 75c-33.137 0-60 26.863-60 60s26.863 60 60 60h100"></path></g></svg>
|
||||
<span>webrimg</span>
|
||||
</a>
|
||||
</p>
|
||||
<style>
|
||||
.webring__title {
|
||||
display: inline-block;
|
||||
border-bottom: 1px solid #777; }
|
||||
|
||||
.webring {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: .5rem; }
|
||||
|
||||
.webring__wrapper {
|
||||
height: 2rem;
|
||||
margin-left: 1rem;
|
||||
padding: .3rem 0 .3rem 1.2rem;
|
||||
border-left: 1px solid #777; }
|
||||
|
||||
.webring svg { width: 1rem; height: 1rem; }
|
||||
a.webring:hover svg * { stroke-width: 40px; }
|
||||
</style>
|
||||
|
|
|
@ -1,10 +1,14 @@
|
|||
{html_sbcont_start}
|
||||
=> / 🏡 go home...
|
||||
{html_sbcont_end}
|
||||
|
||||
# wiki
|
||||
=> /images/t/wiki.png thumbnail
|
||||
a collection of thoughts and projects i have accumulated over the years
|
||||
|
||||
{html_sbcont_start}
|
||||
=> /wiki/category/ 📚 categories
|
||||
{html_sbcont_end}
|
||||
|
||||
{html_filter}
|
||||
{wiki_all}
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
{html_sbcont_start}
|
||||
=> / 🏡 go home...
|
||||
=> /wiki/ 🗃️ go back...
|
||||
{html_sbcont_end}
|
||||
|
||||
{content}
|
||||
|
|
|
@ -6,14 +6,14 @@ modified 2024/03/15
|
|||
category text
|
||||
```
|
||||
|
||||
hey! this is sophie, the swamp witch android of charleville. im a """cyborg plant""" who only types in lowercase. i like to fuck around with computers, electronics, and creating/manipulating digital media. thoughtful simplicity fascinates me, and i love learning to make sense of the physical world through fundamentals, crafting (NOT engineering), and alchemy — botany is neat too but i'm not very good at it yet
|
||||
|
||||
understand life as a chore list, what a blessing this boredom is. you are a spiritual being having a human experience, go meditate next to the biggest alder tree you can find (or any blåhaj)
|
||||
hey! this is your favorite mousegirl sophie, the swamp witch android of charleville, but also a """cyborg plant""". i can only can type in lowercase. i like to fuck around with computers, electronics, and creating/manipulating digital media. thoughtful simplicity fascinates me, and i love learning to make sense of the physical world through fundamentals, crafting (NOT engineering), and alchemy — botany is neat too but i'm not very good at it yet
|
||||
|
||||
=> /wiki/ 🧠 sophie's brian
|
||||
=> /wiki/favorites.ln ⭐ favorites
|
||||
=> /wiki/serial-number.ln 0x 737A6F6669E1
|
||||
=> https://mk.catgirlsfor.science/ daily dose of sophie
|
||||
=> https://mk.catgirlsfor.science/@zvava daily dose of sophie
|
||||
|
||||
squeek i'm just a little mouse squeak squeak
|
||||
|
||||
## bio
|
||||
sophia is a young adult woman trying her best to survive through the arduous process of self-fulfillment, making only the cutest projects doing so — focusing on doing it in my own way, aiming for sophistication through simplicity, and with respect to the natural environment and all its organisms working together
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
# color server
|
||||
```
|
||||
created 2024/03/28
|
||||
category software
|
||||
```
|
||||
|
||||
hue-server is a little color server i wrote. it will advertise a color and you may change it at will. it also comes with a little web client!
|
||||
=> https://zvava.org/api/hue/client zvava.org's current color!
|
||||
|
||||
additionally, it can connect to a ntfy.sh topic to advertise changes in real time, and it also supports http authentication
|
||||
|
||||
=> https://git.zvava.org/zvava/hue-server source code
|
||||
|
||||
24/04/25 — i have disabled authentication on zvava.org 👀
|
||||
|
||||
## usage
|
||||
very simple!
|
||||
|
||||
```
|
||||
$ curl -d "eebfff" https://zvava.org/api/hue
|
||||
$ curl -d "#667557" https://zvava.org/api/hue
|
||||
```
|
||||
|
||||
=> https://zvava.org/api/hue zvava.org's hue api endpoint
|
149
src/zvava.css
149
src/zvava.css
|
@ -8,12 +8,14 @@ body {
|
|||
padding: 0 1rem;
|
||||
margin: 3rem auto 20vh;
|
||||
background-color: black;
|
||||
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="32" fill="dimgray" viewBox="0 0 31 31"><rect x="30" y="30" width="1" height="1"></rect></svg>');
|
||||
background-image: url("/images/bg.png");
|
||||
background-position: center;
|
||||
color: #dddddd;
|
||||
font-family: Ubuntu Mono, monospace;
|
||||
line-height: 1.5rem;
|
||||
font-size: 1.1rem; }
|
||||
font-size: 1.1rem; }
|
||||
|
||||
nav { display: none; }
|
||||
|
||||
.wrap { background: rgba(0, 0, 0, .66); }
|
||||
|
||||
|
@ -60,7 +62,7 @@ pre, blockquote {
|
|||
color: #aaa;
|
||||
background: rgba(0, 0, 0, .5); }
|
||||
|
||||
a {
|
||||
a:not(.sidebar__link) {
|
||||
text-decoration: none;
|
||||
color: #c27ed5;
|
||||
background: rgba(0, 0, 0, .5);
|
||||
|
@ -68,7 +70,7 @@ a {
|
|||
font-family: Ubuntu Mono, monospace;
|
||||
white-space: pre; }
|
||||
|
||||
a:not(.nob4)::before {
|
||||
a:not(.sidebar__link):not(.nob4)::before {
|
||||
content: "\21D2 "; }
|
||||
|
||||
a:focus, a:hover, a.focus {
|
||||
|
@ -88,6 +90,137 @@ a.focus {
|
|||
max-width: 100%; }
|
||||
}
|
||||
|
||||
@media (min-width: 90ch) {
|
||||
body {
|
||||
max-width: unset !important;
|
||||
margin-left: 20ch !important;
|
||||
margin-right: 0 !important;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
overflow-x: hidden; }
|
||||
|
||||
.wrap .sidebar-content { display: none; }
|
||||
.wrap { max-width: 80ch; width: 80ch }
|
||||
nav { display: flex; }
|
||||
}
|
||||
|
||||
@media (min-width: 1300px) {
|
||||
body { margin-left: 10ch; }
|
||||
}
|
||||
|
||||
/* sidebar */
|
||||
|
||||
nav {
|
||||
height: 100vh;
|
||||
width: 20ch;
|
||||
background-color: black;
|
||||
background-image: url("/images/bg2.png");
|
||||
animation: scrollbg 5s infinite linear;
|
||||
border-right: 1.5px solid #313131;
|
||||
flex-direction: column;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
z-index: 1; }
|
||||
|
||||
@keyframes scrollbg {
|
||||
0% { background-position: 0px 0px; }
|
||||
100% { background-position: 128px 128px; }
|
||||
}
|
||||
|
||||
nav .sidebar-content {
|
||||
border-bottom: 1px solid #313131;
|
||||
padding-bottom: 2ch;
|
||||
flex: 1;
|
||||
overflow: hidden scroll;
|
||||
scrollbar-width: thin; }
|
||||
|
||||
nav .sidebar-content::-webkit-scrollbar { width: 4px; }
|
||||
nav .sidebar-content::-webkit-scrollbar-thumb { background: #ffffff; }
|
||||
|
||||
.sidebar__header { line-height: 1.7; }
|
||||
.sidebar__header a { line-height: unset; background: transparent; }
|
||||
.sidebar__header:has(a) { display: flex; justify-content: space-between; }
|
||||
|
||||
.sidebar-content .sidebar__header {
|
||||
padding: 1ch 2ch;
|
||||
color: #eebfff; }
|
||||
|
||||
.sidebar-bottom .sidebar__header {
|
||||
padding: 0 1ch;
|
||||
background: linear-gradient(to right, #422c55 0%, #0005 100%); }
|
||||
|
||||
.sidebar-content pre {
|
||||
padding: .5ch 0 1ch;
|
||||
background: unset;
|
||||
font-weight: normal; }
|
||||
|
||||
.sidebar__link {
|
||||
padding: 0 2ch;
|
||||
display: block;
|
||||
color: #ddd;
|
||||
text-decoration: none;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
text-wrap: nowrap;
|
||||
text-overflow: ellipsis; }
|
||||
|
||||
.sidebar__link::before {
|
||||
content: "";
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 3ch;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
opacity: 0;
|
||||
background: linear-gradient(to bottom, transparent 0%, #c884ff55 50%, transparent 100%);
|
||||
transition: opacity .1s;
|
||||
z-index: -9; }
|
||||
|
||||
.sidebar__link:hover::before, .sidebar__link.focus::before { opacity: 1; }
|
||||
|
||||
/* windows */
|
||||
|
||||
.window {
|
||||
border: 2px solid #5e126f; }
|
||||
|
||||
.window-titlebar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: #eebfff;
|
||||
font-size: .8em;
|
||||
border-bottom: 2px solid #5e126f;
|
||||
background: #18002c;
|
||||
cursor: grab;
|
||||
user-select: none; }
|
||||
|
||||
.window__title { padding: 0 .75ch; flex: 1; }
|
||||
|
||||
.window-titlebar__maximize, .window-titlebar__close {
|
||||
margin-right: 3px;
|
||||
width: 2.25ch; height: 2.25ch;
|
||||
color: #5e126f;
|
||||
background: #000000;
|
||||
border: 1px solid currentColor;
|
||||
cursor: pointer; }
|
||||
|
||||
.window-titlebar__maximize:hover, .window-titlebar__close:hover {
|
||||
color: #c884ff; }
|
||||
|
||||
.window-titlebar__maximize {
|
||||
width: 1.45ch; height: 1.45ch;
|
||||
border-width: .66ch; border-style: double; }
|
||||
|
||||
.window-titlebar__close::before {
|
||||
content: "\02E3";
|
||||
font-size: 3ch;
|
||||
padding-left: .15ch;
|
||||
margin-top: -.15ch;
|
||||
display: block; }
|
||||
|
||||
.window:not(.fake) { /* TODO */ }
|
||||
|
||||
/* lazy mode */
|
||||
|
||||
.lazy-mode {
|
||||
|
@ -123,7 +256,8 @@ a.focus {
|
|||
user-select: text; }
|
||||
|
||||
.lazy-mode img {
|
||||
pointer-events: none }
|
||||
box-sizing: content-box;
|
||||
pointer-events: none; }
|
||||
|
||||
.lazy-mode a {
|
||||
cursor: none;
|
||||
|
@ -131,11 +265,14 @@ a.focus {
|
|||
pointer-events: none;
|
||||
transition: color .1s, text-shadow .3s; }
|
||||
|
||||
.lazy-mode a.focus::after {
|
||||
.lazy-mode a:not(.sidebar__link):not(:has(img)).focus::after {
|
||||
color: #777;
|
||||
font-weight: normal;
|
||||
content: " " attr(href); }
|
||||
|
||||
.lazy-mode a:has(img).focus img {
|
||||
box-shadow: 0 0 .45rem #c884ff; }
|
||||
|
||||
.lazy-mode .cursor {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
|
|
Loading…
Reference in New Issue