This commit is contained in:
parent
6266095111
commit
0755c1ccec
65
README.md
65
README.md
|
@ -1,58 +1,13 @@
|
|||
# zvava.org
|
||||
static website generator (html and gemini) for my personal website [zvava.org](zvava.org)
|
||||
static website generator (html and gemini) for my personal website [zvava.org](https://zvava.org)
|
||||
|
||||
## [to do] rewrite no. 4
|
||||
re write the whole website again but in [wren](https://wren.io) and yeah
|
||||
|
||||
## contributing
|
||||
the `qjs wiki.js` utility is provided to help me (and you!) to create modifications to the wiki
|
||||
the `qjs wiki.js` utility is provided to help me (and you!) to create modifications to the wiki. it has usage information built in, the most useful of which are `new` and `make`. to make development faster you may `alias wiki="qjs wiki.js"`
|
||||
|
||||
usage: `qjs wiki.js command args`
|
||||
|
||||
commands:
|
||||
* `list`: list all wiki pages
|
||||
* `new`: create a new wiki page
|
||||
* `edit`: edit a wiki page
|
||||
* `rm`: delete wiki pages
|
||||
|
||||
each command has it's own arguments, to list use `qjs wiki.js command -h`
|
||||
|
||||
### `list`
|
||||
prints out a list of every single page, takes a combination of characters as an argument
|
||||
|
||||
`usage: qjs wiki.js list [-hlLcTIEAMVHS]`
|
||||
|
||||
* `-`: noop
|
||||
* `h`: display usage information
|
||||
* `t`: show TODOs
|
||||
* `a`: show local links
|
||||
* `d`: show dead local links
|
||||
* `l`: list categories of pages as well
|
||||
* `p`: add padding to the list :)
|
||||
* `c`: sort by created date instead of modified date
|
||||
|
||||
> using both `a` and `d` is identical to using just `d`
|
||||
|
||||
you can filter by categories using the captial first letter of a category;
|
||||
|
||||
`s`tub (no category), `T`ext, `I`nfo, `E`vent, `A`rt, `M`usic, `V`ideo, `H`ardware, `S`oftware
|
||||
|
||||
### `edit`
|
||||
makes changes to a page
|
||||
|
||||
`usage: qjs wiki.js edit [arg] page`
|
||||
|
||||
argument:
|
||||
* `(no argument)`: open the page in nano
|
||||
* `-h --help`: display usage information
|
||||
* `-m --modify`: set modified date to today's date
|
||||
|
||||
### `rm`
|
||||
delete a page or pages. if you need to be safe you can type out pages to remove first, then go up in history to confirm the deletion by adding `-y` to the end of the command
|
||||
|
||||
`usage: qjs wiki.js rm [-h] [pages]`
|
||||
|
||||
* `-h --help`: display usage information
|
||||
* `-y --yes`: confirm deletion
|
||||
|
||||
### `new`
|
||||
### new page
|
||||
create a new wiki page with placeholder content
|
||||
|
||||
`usage: qjs wiki.js new page [args...]`
|
||||
|
@ -79,15 +34,15 @@ add content:
|
|||
* `-a --alt`: set alt text of previous image/link
|
||||
|
||||
## development
|
||||
run `qjs make.js` to create out/, out/gemini/, and out/www/, then generate contents
|
||||
run `qjs make.js` (or `wiki make` if you have the alias) to create out/, out/gemini/, and out/www/, then generate contents
|
||||
|
||||
run `webserver 80 out/www/` (`npm i -g webserver`) to debug html output
|
||||
run `webserver 8080 out/www/` (`npm i -g webserver`) to debug html output
|
||||
https://github.com/mbrubeck/agate
|
||||
run `agate --content out/gemini/ --host localhost` to debug gemini output ([agate](https://github.com/mbrubeck/agate))
|
||||
|
||||
## production
|
||||
make sure all changes are committed and pushed
|
||||
|
||||
run `publish.bat` on windows or `publish.sh` on unix and enter password to sync changes with the webserver
|
||||
run `qjs wiki.js publish` and enter password to sync changes with the webserver
|
||||
|
||||
remote server will fetch the latest version of this repo, and run the publish.sh script. this builds the site remotely and copies `out/gemini/` to `/var/gemini/content/` and `out/www/` to `/var/www/`
|
||||
remote server will fetch the latest version of this repo, and run the publish.sh script. this builds the site remotely and copies `out/gemini/` to `/var/gemini/content/` and `out/www/` to `/var/www/`sass
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
zvava.org {
|
||||
# discrimination
|
||||
@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 {
|
||||
uri strip_prefix /media
|
||||
file_server {
|
||||
root /var/lib/syncthing/zvava.org.media/
|
||||
hide .*
|
||||
browse /etc/caddy/browse.tmpl
|
||||
pass_thru
|
||||
}
|
||||
}
|
||||
|
||||
# wiki
|
||||
root * /var/www
|
||||
file_server
|
||||
|
||||
# firefox fix
|
||||
rewrite /favicon.ico /images/favicon.ico
|
||||
# inline files fix
|
||||
@inline path *.ass *.bat *.txt
|
||||
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
|
||||
respond `{"code": {err.status_code}, "message": "{err.message}"}`
|
||||
}
|
||||
|
||||
@404 expression {err.status_code} == 404
|
||||
handle @404 {
|
||||
header Content-Type "text/html; charset=utf-8"
|
||||
header -Content-Disposition
|
||||
rewrite * /wiki/404.html
|
||||
file_server
|
||||
}
|
||||
|
||||
handle {
|
||||
respond "{err.status_code} — {err.status_text}"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
magenta.zvava.org {
|
||||
root * /var/magenta.www
|
||||
file_server
|
||||
|
||||
handle_errors {
|
||||
@404 expression {err.status_code} == 404
|
||||
rewrite @404 /404.html
|
||||
file_server
|
||||
}
|
||||
}
|
||||
|
||||
git.zvava.org {
|
||||
reverse_proxy * localhost:8080
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
{{- define "icon"}}
|
||||
{{- if .IsDir}}
|
||||
📁
|
||||
{{- else if .HasExt ".jpg" ".jpeg" ".png" ".gif" ".webp" ".tiff" ".bmp" ".heif" ".heic" ".svg" ".ico"}}
|
||||
🖼️
|
||||
{{- else if .HasExt ".mp4" ".mov" ".m4v" ".mpeg" ".mpg" ".avi" ".ogg" ".webm" ".mkv" ".vob" ".gifv" ".3gp"}}
|
||||
🎞️
|
||||
{{- else if .HasExt ".mp3" ".m4a" ".aac" ".ogg" ".flac" ".wav" ".wma" ".midi" ".cda"}}
|
||||
💿
|
||||
{{- else if .HasExt ".csv" ".tsv" ".json" ".json5" ".jsonc" ".ini" ".inc" ".toml" ".conf" ".csproj"}}
|
||||
🗒️
|
||||
{{- else if .HasExt ".html" ".htm" ".pdf" ".doc" ".docx" ".odt" ".fodt" ".rtf" ".xls" ".xlsx" ".ods" ".fods" ".ppt" ".pptx" ".odp" ".fodp"}}
|
||||
📑
|
||||
{{- else if .HasExt ".zip" ".gz" ".xz" ".tar" ".7z" ".rar" ".xz" ".zst"}}
|
||||
📦
|
||||
{{- else if .HasExt ".ps1" ".bash" ".sh" ".wren" ".bat" ".exe"}}
|
||||
💾
|
||||
{{- else if .HasExt ".iso" ".img" ".dsk" ".deb" ".dpkg" ".rpm" ".exe" ".rmskin" ".appimage" ".msi" ".apk" ".dmg"}}
|
||||
💽
|
||||
{{- else if .HasExt ".md" ".mdown" ".markdown" ".gmi"}}
|
||||
📝
|
||||
{{- else if .HasExt ".ttf" ".otf" ".woff" ".woff2" ".eof"}}
|
||||
🔣
|
||||
{{- else if .HasExt ".com" ".dll" ".php" ".so" ".go" ".js" ".css" ".ts" ".py" ".pyc" ".pyo" ".cs" ".c" ".jar"}}
|
||||
🧩
|
||||
{{- else if .HasExt ".sql" ".db" ".sqlite" ".bak" ".mdb"}}
|
||||
🗄️
|
||||
{{- else if .HasExt ".eml" ".email" ".mailbox" ".mbox" ".msg"}}
|
||||
✉️
|
||||
{{- else if .HasExt ".crt" ".pem" ".x509" ".cer" ".ca-bundle"}}
|
||||
🧾
|
||||
{{- else if .HasExt ".key" ".keystore" ".jks" ".p12" ".pfx" ".pub"}}
|
||||
🔑
|
||||
{{- else}}
|
||||
📄
|
||||
{{- end}}
|
||||
{{- end}}
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>{{html .Name}}</title>
|
||||
<link rel="canonical" href="{{.Path}}/" />
|
||||
<meta charset="utf-8">
|
||||
<meta name="color-scheme" content="light dark">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<style>
|
||||
body {
|
||||
max-width: 80ch;
|
||||
margin: 1rem 2rem;
|
||||
font-family: monospace;
|
||||
font-size: 1.1rem; }
|
||||
|
||||
hr { border: none; height: 1px;
|
||||
background: #444;
|
||||
margin: 1rem 0; }
|
||||
|
||||
.entry {
|
||||
display: flex; }
|
||||
|
||||
.entry .date {
|
||||
width: 10ch; }
|
||||
|
||||
.entry .a {
|
||||
padding: 0 1ch;
|
||||
flex: 1;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
white-space: nowrap; }
|
||||
|
||||
a[href]:hover, a[href]:focus {
|
||||
color: #b58bf9; }
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body {
|
||||
background: #1c1c1c;
|
||||
color: #bbb; }
|
||||
|
||||
a {
|
||||
color: #eee; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="entries">
|
||||
<div class="entry">
|
||||
<span class="date"></span>
|
||||
<span class="a">📂 /{{range $i, $crumb := .Breadcrumbs}}<a href="{{html $crumb.Link}}">{{if eq $i 0}}media{{else}}{{html $crumb.Text}}{{end}}</a>/{{end}}</span>
|
||||
<span class="size">
|
||||
<b>{{.NumDirs}}</b> dir{{if ne 1 .NumDirs}}s{{end}}
|
||||
<b>{{.NumFiles}}</b> file{{if ne 1 .NumFiles}}s{{end}}
|
||||
</span>
|
||||
</div>
|
||||
<hr>
|
||||
{{- range .Items}}
|
||||
<div class="entry">
|
||||
<span class="date">{{html (.HumanModTime "2006/01/02")}}</span>
|
||||
<span class="a">{{template "icon" .}} <a href="{{html .URL}}">{{html .Name}}</a></span>
|
||||
<span class="size">{{if .IsDir}}—{{else}}{{.HumanSize}}{{end}}</span>
|
||||
</div>
|
||||
{{- end}}
|
||||
<hr>
|
||||
<div class="entry">
|
||||
<span class="date"></span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
28
make.js
28
make.js
|
@ -188,13 +188,13 @@ function generateGemini() {
|
|||
|
||||
function generateHTML(files) {
|
||||
print("\x1b[90m->\x1b[0m generating html site...")
|
||||
|
||||
|
||||
files["stats"] = files["stats"] // add graph to stats page
|
||||
.replace("=> https://zvava.org/stats.html requires javascript to work :l", "{stats}")
|
||||
|
||||
|
||||
files["wiki/about-site"] = files["wiki/about-site"] // alternate gemini links to https on about page
|
||||
.replace("=> https://zvava.org 🕸️ view html version", "=> gemini://zvava.org 🚀 view gemini version")
|
||||
|
||||
|
||||
|
||||
let count = 0
|
||||
// iterate over each page and render final html
|
||||
|
@ -243,11 +243,13 @@ function generateHTML(files) {
|
|||
.replace(/^[-*+] +(.*)/, "<span class=\"ui\">$1</span>")
|
||||
.replace(/^([0-9a-bA-B\.]+)\. +(.*)/, "<span class=\"oi\" data-i=\"$1\">$2</span>")
|
||||
|
||||
if (f == "wiki/index" && l.startsWith("<a href=\"/wiki/")) {
|
||||
let start = l.indexOf("/wiki/") + 6 // get start of link
|
||||
let end = l.indexOf(".html", start) // get end of link
|
||||
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" && l.startsWith("<a href=\"/wiki/")) { // 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.category.join(" ")}">`) // add category attribute
|
||||
l = l.replace(">", ` data-category="${page.category.join(" ")}">`) // add
|
||||
}
|
||||
|
||||
// will this line be considered for its spacing?
|
||||
|
@ -283,7 +285,7 @@ function generateHTML(files) {
|
|||
output = output.replace("<p>{stats}</p>\n", templates["stats.html"]) // replace statustics tempalte
|
||||
+ templates["viewcounter.html"].replace("{url}", "/" + f + ".html")
|
||||
} else if (f == "wiki/index") { // wiki home page
|
||||
// use filter template
|
||||
// use filter template
|
||||
output = output.replace("<p>{html_filter}<br>\n", templates["filter.html"] + "<p>")
|
||||
// pass down data-category attribute from <a> to <p>s and <pre>s
|
||||
.replace(/<p><a (href=".+?") (data-category=".+?")>(.+?)<\/a><\/p>\n<pre>/gm, "<p $2><a $1>$3</a></p>\n<pre $2>")
|
||||
|
@ -331,11 +333,11 @@ function prependRelevantEmoji(x) {
|
|||
let e = ""
|
||||
switch (x) {
|
||||
case "text": e += "📝"; break
|
||||
case "info": e += "🧠"; break
|
||||
case "event": e += "🍾"; break
|
||||
case "art": e += "🎨"; break
|
||||
case "music": e += "🎵"; break
|
||||
case "video": e += "📺"; break
|
||||
case "info": e += "📑"; break
|
||||
case "event": e += "📅"; break
|
||||
case "art": e += "🖼️"; break
|
||||
case "music": e += "🎶"; break
|
||||
case "video": e += "🎞️"; break
|
||||
case "hardware": e += "🔧"; break
|
||||
case "software": e += "💾"; break
|
||||
}
|
||||
|
|
|
@ -15,15 +15,15 @@
|
|||
<div class="label">
|
||||
<label class="all-label" for="all" >*️⃣ all</label>
|
||||
<label class="text-label" for="text" >📝 text</label>
|
||||
<label class="info-label" for="info" >🧠 info</label>
|
||||
<label class="info-label" for="info" >📑 info</label>
|
||||
<label class="hardware-label" for="hardware">🔧 hardware</label>
|
||||
<label class="software-label" for="software">💾 software</label>
|
||||
</div>
|
||||
<div class="label">
|
||||
<label class="event-label" for="event" >🍾 event</label>
|
||||
<label class="art-label" for="art" >🎨 art</label>
|
||||
<label class="music-label" for="music" >🎵 music</label>
|
||||
<label class="video-label" for="video" >📺 video</label>
|
||||
<label class="event-label" for="event" >📅 event</label>
|
||||
<label class="art-label" for="art" >🖼️ art</label>
|
||||
<label class="music-label" for="music" >🎶 music</label>
|
||||
<label class="video-label" for="video" >🎞️ video</label>
|
||||
</div>
|
||||
</div>
|
||||
</details>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
=> /images/header.png welcome to zvava.org ({build_info_summary})
|
||||
|
||||
hey! i'm sophie (she/her) and i also go by zvava or névtelen. 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 goes to the main wiki page where you can filter pages by category
|
||||
hey! i'm sophie (she/her) and i go by zvava. 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 goes to the main wiki page where you can filter pages by category. sad girl 4 life
|
||||
|
||||
## navigation
|
||||
=> /wiki/ 📚 wiki
|
||||
|
@ -16,6 +16,7 @@ hey! i'm sophie (she/her) and i also go by zvava or névtelen. you are currently
|
|||
=> https://mk.catgirlsfor.science/@zvava 🔮 fediverse
|
||||
=> https://matrix.to/#/%23zvavspace%3Acatgirl.cloud 🌐 matrix
|
||||
=> https://git.zvava.org/zvava 💾 git forge
|
||||
=> https://keyoxide.org/5386D9E7ED1C49BEE15B9F32074FE2D02D45891C 🔏 keyoxide
|
||||
=> https://www.buymeacoffee.com/zvavaxox 🍺 buy me a beer!
|
||||
=> https://webring.xxiivv.com/#icons 🪐 merveilles webring
|
||||
|
||||
|
@ -29,10 +30,9 @@ hey! i'm sophie (she/her) and i also go by zvava or névtelen. you are currently
|
|||
fediverse: @zvava@mk.catgirlsfor.science
|
||||
matrix: @zvava:catgirl.cloud
|
||||
email: z@zvava.org
|
||||
```
|
||||
|
||||
### i also check
|
||||
```
|
||||
discord: @zvava
|
||||
revolt: @zvava#7247
|
||||
discord: @zvava
|
||||
```
|
||||
=> /media/zvava.asc 🔒 public key
|
||||
|
||||
wawawawawawa
|
||||
|
|
25
wiki.js
25
wiki.js
|
@ -8,6 +8,7 @@ function main() {
|
|||
|
||||
switch (scriptArgs[0]) {
|
||||
case "publish": return publish()
|
||||
case "make": return make()
|
||||
case "list": return list()
|
||||
case "new": return newPage()
|
||||
case "edit": return edit()
|
||||
|
@ -21,6 +22,7 @@ function main() {
|
|||
" new create a new wiki page\n" +
|
||||
" edit edit a wiki page\n" +
|
||||
" rm delete wiki pages\n" +
|
||||
" make run make script\n\n" +
|
||||
" publish run publish script\n\n" +
|
||||
"each command has it's own arguments, to list use -h\n" +
|
||||
"")
|
||||
|
@ -44,11 +46,11 @@ function prependRelevantEmoji(x) {
|
|||
let e = ""
|
||||
switch (x) {
|
||||
case "text": e += "📝"; break
|
||||
case "info": e += "🧠"; break
|
||||
case "event": e += "🍾"; break
|
||||
case "art": e += "🎨"; break
|
||||
case "music": e += "🎵"; break
|
||||
case "video": e += "📺"; break
|
||||
case "info": e += "📑"; break
|
||||
case "event": e += "📅"; break
|
||||
case "art": e += "🖼️"; break
|
||||
case "music": e += "🎶"; break
|
||||
case "video": e += "🎞️"; break
|
||||
case "hardware": e += "🔧"; break
|
||||
case "software": e += "💾"; break
|
||||
}
|
||||
|
@ -70,6 +72,19 @@ function publish() {
|
|||
print(`publish: cannot run on this platform (${os.platform})`)
|
||||
}
|
||||
|
||||
function make() {
|
||||
if (scriptArgs.includes("-h") || scriptArgs.includes("--help"))
|
||||
return print(
|
||||
"usage: qjs wiki.js make\n\n" +
|
||||
"literally just runs the make script\n" +
|
||||
"")
|
||||
|
||||
if (canRunExec())
|
||||
return os.exec(["qjs", "make.js"])
|
||||
|
||||
print(`publish: cannot run on this platform (${os.platform})`)
|
||||
}
|
||||
|
||||
function list() {
|
||||
let args = (scriptArgs[1] || "")
|
||||
if (args.includes("h"))
|
||||
|
|
Loading…
Reference in New Issue