diff options
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | Makefile | 88 | ||||
-rwxr-xr-x | ht.awk | 79 | ||||
-rwxr-xr-x | ht.sh | 66 | ||||
-rw-r--r-- | ideas.org | 8 | ||||
-rw-r--r-- | src/_foot.htm | 6 | ||||
-rw-r--r-- | src/_head.htm | 14 | ||||
-rw-r--r-- | src/_index.htm | 7 | ||||
-rw-r--r-- | src/beans.html | 21 | ||||
-rw-r--r-- | src/favicon.ht | 15 | ||||
-rw-r--r-- | src/gcl/index.html | 21 | ||||
-rw-r--r-- | src/shameless-self-promotion/index.html | 11 | ||||
-rw-r--r-- | src/static/casa.css | 32 | ||||
-rw-r--r-- | src/static/rss.xml | 27 | ||||
-rw-r--r-- | tmpl.index.htm | 16 | ||||
-rw-r--r-- | tmpl.page.htm | 8 |
16 files changed, 421 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..af8a313 --- /dev/null +++ b/.gitignore | |||
@@ -0,0 +1,2 @@ | |||
1 | .tmp | ||
2 | build/ | ||
diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..5b3cadd --- /dev/null +++ b/Makefile | |||
@@ -0,0 +1,88 @@ | |||
1 | ## HAT TRICK -*- tab-width: 8; -*- | ||
2 | # (C) 2022 C. Duckworth | ||
3 | |||
4 | UPLOAD_TARGET = hetzner:/var/www/acdw.casa/ | ||
5 | |||
6 | SITE_TITLE = acdw.casa | ||
7 | |||
8 | INPUT = src | ||
9 | BUILD = build | ||
10 | LASTB = .last_build | ||
11 | |||
12 | HTAWK = ./ht.awk | ||
13 | HTSH = ./ht.sh | ||
14 | HTMK = ht.mk | ||
15 | HT = ${HTAWK} ${HTSH} ${HTMK} | ||
16 | |||
17 | T = .tmp | ||
18 | TMK = $T/mk | ||
19 | TPG = $T/ps | ||
20 | |||
21 | PTMPL = tmpl.page.htm | ||
22 | PTMPC = \ | ||
23 | <title>$$(title)</title> \ | ||
24 | $$(body) | ||
25 | PTMPR = \ | ||
26 | $$hb: $$ht ; \ | ||
27 | ${HTAWK} < '$$ht' | \ | ||
28 | env HTTMP='$T' HTENV='$T/\$$<.env' HTOUT='\$$@' \ | ||
29 | ${HTSH} '${PTMPL}' > '\$$@' | ||
30 | |||
31 | ITMPL = tmpl.index.htm | ||
32 | ITMPC = \ | ||
33 | <title>${SITE_TITLE}</title> \ | ||
34 | <ul id="idx"> \ | ||
35 | $$(for p in "$T"/*.env; do \ | ||
36 | . "$$p"; \ | ||
37 | print "<li><a href=\"$$HTOUT\">$$(title)</a></li>"; \ | ||
38 | done) \ | ||
39 | </ul> | ||
40 | ITMPR = \ | ||
41 | index.html: ${ITMPL} $$(cat ${TPG}); \ | ||
42 | env HTTMP='$T' HTOUT='\$$@' \ | ||
43 | ${HTSH} "${ITMPL}" < /dev/null > '\$$@' | ||
44 | |||
45 | TMPL = ${PTMPL} ${ITMPL} | ||
46 | BUILD_INPUTS = ${INPUT}/* ${TMPL} ${HT} | ||
47 | |||
48 | ${BUILD}: ${BUILD_INPUTS} | ||
49 | @touch ${LASTB} | ||
50 | @mkdir -p ${BUILD} | ||
51 | cp -a ${BUILD_INPUTS} $@ | ||
52 | ${MAKE} -C $@ -f ${HTMK} build | ||
53 | |||
54 | ${HTMK}: Makefile ${INPUT}/*.ht $T | ||
55 | @printf '%s' 'Generating "$@"...' | ||
56 | @: > '$@' | ||
57 | @: > '${TPG}' | ||
58 | |||
59 | @for ht in $$(find ${INPUT} -type f -name '*.ht'); do \ | ||
60 | ht="$$(echo "$$ht" | sed 's#${INPUT}/##')"; \ | ||
61 | hb="$${ht}ml"; \ | ||
62 | printf '%s ' "$$hb" >> "${TPG}"; \ | ||
63 | printf '%s\n' "${PTMPR}"; \ | ||
64 | done >> '$@' | ||
65 | |||
66 | @printf '%s\n' "${ITMPR}" >> '$@' | ||
67 | @printf "build: $$(cat ${TPG}) index.html" >> '$@' | ||
68 | @printf '%s\n' 'done' | ||
69 | |||
70 | $T: ; mkdir -p "$@" | ||
71 | ${PTMPL}: ; printf '${PTMPC}' > '$@' | ||
72 | ${ITMPL}: ; printf '${ITMPC}' > '$@' | ||
73 | |||
74 | .PHONY: clean clean-build nuke | ||
75 | clean: ; -rm -rf ${BUILD} ${HTMK} $T ${LASTB} | ||
76 | clean-build: | ||
77 | rm -rf '${BUILD}/$T' | ||
78 | for file in ${BUILD}/*; do \ | ||
79 | case "$$file" in \ | ||
80 | *.ht|*.sh|*.htm|*.mk|*.awk) rm -rf "$$file" ;; \ | ||
81 | esac \ | ||
82 | done | ||
83 | nuke: clean ; -rm ${TMPL} | ||
84 | |||
85 | .PHONY: publish | ||
86 | publish: build clean-build | ||
87 | scp -r ${BUILD}/* '${UPLOAD_TARGET}'; \ | ||
88 | |||
diff --git a/ht.awk b/ht.awk new file mode 100755 index 0000000..5328361 --- /dev/null +++ b/ht.awk | |||
@@ -0,0 +1,79 @@ | |||
1 | #!/usr/bin/awk -f | ||
2 | # HAT TRICK | ||
3 | # (C) 2022 C. Duckworth | ||
4 | |||
5 | # ht.awk converts mostly-html (with some conveniences) to actual html | ||
6 | |||
7 | function bufpush(s) { | ||
8 | BUF = BUF (BUF ? "\n" : "") s; | ||
9 | } | ||
10 | |||
11 | function buflush() { | ||
12 | if (BUF) print BUF; | ||
13 | BUF = ""; | ||
14 | if (tag && (tag != "html")) print "</" tag ">"; | ||
15 | } | ||
16 | |||
17 | function esc(t) { | ||
18 | gsub(/&/, "\\&", t); | ||
19 | gsub(/</, "\\<", t); | ||
20 | gsub(/>/, "\\>", t); | ||
21 | return t; | ||
22 | } | ||
23 | |||
24 | /^;/ { sub(/^;/,""); print "<!--", esc($0), "-->"; next; } | ||
25 | |||
26 | /^</ { # Raw HTML | ||
27 | if (! (tag == "html")) tag = "html"; | ||
28 | bufpush($0); | ||
29 | next; | ||
30 | } | ||
31 | |||
32 | /^=>/ { # Links (Gemini-style) | ||
33 | link = "<a href=\"" esc($2) "\">" esc($3); | ||
34 | for (i=4;i<=NF;i++) link = link " " esc($i); | ||
35 | link = link "</a>"; | ||
36 | bufpush(link); | ||
37 | next; | ||
38 | } | ||
39 | |||
40 | /^-/ { # Unordered lists | ||
41 | if (! (tag == "ul")) tag = "ul"; | ||
42 | esc($0); | ||
43 | sub(/^-[ \t]*/, "<li>"); | ||
44 | } | ||
45 | |||
46 | /^[0-9]+\./ { # Ordered lists | ||
47 | if (! (tag == "ol")) tag = "ol"; | ||
48 | esc($0); | ||
49 | sub(/^[0-9]+\.[ \t]/, "<li>"); | ||
50 | } | ||
51 | |||
52 | /^>/ { # Blockquotes | ||
53 | if (! (tag == "blockquote")) tag = "blockquote"; | ||
54 | sub(/^>[ \t]*/,""); | ||
55 | esc($0); | ||
56 | } | ||
57 | |||
58 | /^#+/ { # Headers | ||
59 | match($0, /^#+/); | ||
60 | if (! (tag == "h" RLENGTH)) { | ||
61 | buflush(); | ||
62 | tag = "h" RLENGTH; | ||
63 | } | ||
64 | sub(/^#+[ \t]*/,""); | ||
65 | esc($0); | ||
66 | } | ||
67 | |||
68 | /^$/ { | ||
69 | buflush(); | ||
70 | tag = ""; | ||
71 | } | ||
72 | |||
73 | /./ { | ||
74 | if (! tag) tag = "p"; | ||
75 | if (! BUF) bufpush("<" tag ">"); | ||
76 | bufpush($0); | ||
77 | } | ||
78 | |||
79 | END { buflush(); } | ||
diff --git a/ht.sh b/ht.sh new file mode 100755 index 0000000..de58fe1 --- /dev/null +++ b/ht.sh | |||
@@ -0,0 +1,66 @@ | |||
1 | #!/bin/sh | ||
2 | # HAT TRICK | ||
3 | # (C) 2022 C. Duckworth | ||
4 | |||
5 | [ "x$DEBUG" = "xYES" ] && set -x | ||
6 | |||
7 | : "${HTDAT:=$(date +%s)}" | ||
8 | : "${HTTMP:=/tmp/ht}"; mkdir -p "$HTTMP" | ||
9 | : "${HTENV:=$HTTMP/env-$HTDAT.sh}" | ||
10 | : "${HTBOD:=$HTTMP/bod-$HTDAT.txt}" | ||
11 | export HTDAT HTTMP HTENV HTBOD | ||
12 | |||
13 | HT_TMPL_COUNT=1 | ||
14 | HT_TMPL_PRE=: | ||
15 | |||
16 | print() { # print STRING... | ||
17 | ## A sane version of `echo`. | ||
18 | printf '%s\n' "$*" | ||
19 | } | ||
20 | |||
21 | htt() { # htt FILES... | ||
22 | # Like `cat`, but with templating. | ||
23 | ht_end="ht_main_$HTDAT_$HT_TMPL_COUNT" # be extra double sure | ||
24 | eval "$(print "cat <<$ht_end"; cat "$@"; print; print "$ht_end")" | ||
25 | HT_TMPL_COUNT=$(expr $HT_TMPL_COUNT + 1) | ||
26 | } | ||
27 | |||
28 | ht_build_env() { # ht_build_env FILE... | ||
29 | print "body() { cat \"$HTBOD\"; }" > "$HTENV" | ||
30 | while read -r line; do | ||
31 | case "$line" in | ||
32 | *@@*:*@@*) # "simple" metadata; just a string | ||
33 | print "$line" | | ||
34 | sed 's/.*@@\([^:]*\): \?\(.*\)@@.*/\1() { print "\2"; }/' | ||
35 | ;; | ||
36 | *@@*::*@@*) # "complex" metadata: can be anything | ||
37 | print "$line" | | ||
38 | sed 's/.*@@\([^:]*\):: \?\(.*\)@@.*/\1() { \2 ; }/' | ||
39 | ;; | ||
40 | esac >> "$HTENV" | ||
41 | # Still print the line to the body (no need to escape or w/e) | ||
42 | print "$line" >> "$HTBOD" | ||
43 | done | ||
44 | env | grep '^HT' | sort | uniq >> "$HTENV" | ||
45 | } | ||
46 | |||
47 | ht_main() { # main TEMPLATE < INPUT | ||
48 | ## Apply TEMPLATE to INPUT and print it. | ||
49 | # TEMPLATE will be interpreted as a heredoc. | ||
50 | if [ $# -eq 0 ]; then | ||
51 | print "ht.sh TEMPLATE < INPUT" >&2 | ||
52 | exit 1 | ||
53 | fi | ||
54 | |||
55 | eval "ht_build_env; . \"$HTENV\"; print \"\$(htt \"\$@\")\";"; | ||
56 | } | ||
57 | |||
58 | # To keep this POSIX-compliant, we can't use a bashism like | ||
59 | # [[ "$0" == # "$BASH_SOURCE[0]" ]]. However, there are still ways to guess | ||
60 | # whether the user is sourcing this file as a library or executing it as a | ||
61 | # script. | ||
62 | |||
63 | case "$0" in | ||
64 | *ht.sh) ht_main "$@" ;; | ||
65 | *) print "Sourcing ht.sh" ;; | ||
66 | esac | ||
diff --git a/ideas.org b/ideas.org new file mode 100644 index 0000000..27b15e5 --- /dev/null +++ b/ideas.org | |||
@@ -0,0 +1,8 @@ | |||
1 | #+TITLE: ideas for hat-trick | ||
2 | |||
3 | * Syntax: ht.awk | ||
4 | |||
5 | It'd be great to have a format that could triple into HTML, Gemini, and Gopher. Gemini-like, line-based syntax would be easiest to work with, i think. | ||
6 | |||
7 | The current separation into paragraphs with blocks is a good idea. Also, starting a line with ~<~ /within/ a paragraph could be a good signal that the following is HTML code. Maybe auto-close the tag? | ||
8 | |||
diff --git a/src/_foot.htm b/src/_foot.htm new file mode 100644 index 0000000..287b2ba --- /dev/null +++ b/src/_foot.htm | |||
@@ -0,0 +1,6 @@ | |||
1 | <footer> | ||
2 | $(case "$(title)" in ("") ;; (*) print "<a href=\"./index.html\">back</a>" ;; esac) | ||
3 | <span id="copyright">(C) 2022 C. Duckworth</span> | ||
4 | </footer> | ||
5 | </body> | ||
6 | </html> | ||
diff --git a/src/_head.htm b/src/_head.htm new file mode 100644 index 0000000..762965e --- /dev/null +++ b/src/_head.htm | |||
@@ -0,0 +1,14 @@ | |||
1 | <!DOCTYPE html> | ||
2 | <html lang="en"> | ||
3 | <head> | ||
4 | <meta charset="utf-8"> | ||
5 | <meta http-equiv="x-ua-compatible" content="ie=edge"> | ||
6 | <meta name="viewport" | ||
7 | content="width=device-width,initial-scale=1,shrink=to-fit=no"> | ||
8 | <title>$(title)</title> | ||
9 | <link rel="shortcut icon" | ||
10 | href="data:image/gif;base64,R0lGODdhEAAQAIAAAAByL8zAGiwAAAAAEAAQAAACK4wNqQsX+1hD6kiaXKxQb+ZZYChmpGNinfpxV/q02dzUrx1L+Lzlp60LFgAAOw==" /> | ||
11 | <link rel="stylesheet" type="text/css" href="static/casa.css"> | ||
12 | <link rel="alternate" type="application/atom+xml" href="static/rss.xml"> | ||
13 | </head> | ||
14 | <body> | ||
diff --git a/src/_index.htm b/src/_index.htm new file mode 100644 index 0000000..6b7b809 --- /dev/null +++ b/src/_index.htm | |||
@@ -0,0 +1,7 @@ | |||
1 | <p>Ahoy! This here is my little home-away-from-home on the interwebs. | ||
2 | I'm currently experimenting with a custom little <abbr title="static site generator">SSG</abbr> | ||
3 | I'm calling <strong>HAT TRICK</strong>. | ||
4 | I should probably throw the source up somewhere, but I haven't yet. | ||
5 | </p> | ||
6 | |||
7 | |||
diff --git a/src/beans.html b/src/beans.html new file mode 100644 index 0000000..ff89934 --- /dev/null +++ b/src/beans.html | |||
@@ -0,0 +1,21 @@ | |||
1 | html,body { | ||
2 | min-height: 100vh; | ||
3 | margin:0; padding: 0; | ||
4 | } | ||
5 | |||
6 | html { | ||
7 | font: 18px serif; | ||
8 | background: #385180; | ||
9 | } | ||
10 | |||
11 | body { | ||
12 | max-width: 79ch; | ||
13 | padding: 0 2ch; | ||
14 | margin: 0 auto; | ||
15 | background: #405990; | ||
16 | color: white; | ||
17 | } | ||
18 | |||
19 | a { | ||
20 | color: yellow; | ||
21 | } | ||
diff --git a/src/favicon.ht b/src/favicon.ht new file mode 100644 index 0000000..b9df118 --- /dev/null +++ b/src/favicon.ht | |||
@@ -0,0 +1,15 @@ | |||
1 | ;@@title: Embedded data-url favicon@@ | ||
2 | |||
3 | You might notice that I have a <b>new favicon</b> on this site. | ||
4 | I didn't want to make a whole nother request, so I took a page from | ||
5 | => http://flower.codes/2022/05/10/disabling-favicon.html flower.codes | ||
6 | (who disabled their favicon completely) and made my favicon a <code>data</code> uri. | ||
7 | |||
8 | I thought it might be complicated, but it was really pretty ding dang easy. | ||
9 | I found an easy-to-use | ||
10 | => https://www.adminbooster.com/tool/data_uri file-to-data-uri converter tool | ||
11 | and uploaded a little image I made in the | ||
12 | <abbr title="GNU Image Manipulation Program">GIMP</abbr>. I tried PNG and GIF. | ||
13 | GIF was much smaller, so that's what I went with. | ||
14 | |||
15 | Anyway, now you should see a little house on the tab you've loaded this on! Yay. | ||
diff --git a/src/gcl/index.html b/src/gcl/index.html new file mode 100644 index 0000000..3357702 --- /dev/null +++ b/src/gcl/index.html | |||
@@ -0,0 +1,21 @@ | |||
1 | <!DOCTYPE html> | ||
2 | <html> | ||
3 | <head> | ||
4 | <meta charset="utf-8"> | ||
5 | <title>Good Choices License</title> | ||
6 | <style> | ||
7 | body{max-width:78ch;padding:2ch;margin:auto;font:24px serif;} | ||
8 | h1{font-size:2em;} | ||
9 | </style> | ||
10 | </head> | ||
11 | <body> | ||
12 | <h1>Good Choices License</h1> | ||
13 | <p>Everyone is permitted to do whatever they like with this software | ||
14 | without limitation. This software comes without any warranty | ||
15 | whatsoever, but with two pieces of advice:</p> | ||
16 | <ul> | ||
17 | <li>Be kind to yourself.</li> | ||
18 | <li>Make good choices.</li> | ||
19 | </ul> | ||
20 | </body> | ||
21 | </html> | ||
diff --git a/src/shameless-self-promotion/index.html b/src/shameless-self-promotion/index.html new file mode 100644 index 0000000..f4c5710 --- /dev/null +++ b/src/shameless-self-promotion/index.html | |||
@@ -0,0 +1,11 @@ | |||
1 | <html> | ||
2 | <head> | ||
3 | <title>Shameless self-promotion!</title> | ||
4 | </head> | ||
5 | <body> | ||
6 | <h1>shameless</h1> | ||
7 | <h2>self</h2> | ||
8 | <h3>promotion</h3> | ||
9 | <p>what can i say, i'm a cool guy.</p> | ||
10 | </body> | ||
11 | </html> | ||
diff --git a/src/static/casa.css b/src/static/casa.css new file mode 100644 index 0000000..36bdda0 --- /dev/null +++ b/src/static/casa.css | |||
@@ -0,0 +1,32 @@ | |||
1 | html { | ||
2 | min-height: 100vh; | ||
3 | margin:0; padding: 0; | ||
4 | } | ||
5 | |||
6 | html { | ||
7 | font: 18px serif; | ||
8 | } | ||
9 | |||
10 | body { | ||
11 | max-width: 79ch; | ||
12 | margin: 0 auto; | ||
13 | padding: 0 2ch; | ||
14 | background: #385180; | ||
15 | color: white; | ||
16 | } | ||
17 | |||
18 | main { | ||
19 | max-width: 79ch; | ||
20 | padding: 2ch; | ||
21 | margin: auto; | ||
22 | background: #405990; | ||
23 | } | ||
24 | |||
25 | a { | ||
26 | color: yellow; | ||
27 | } | ||
28 | |||
29 | footer { | ||
30 | text-align: right; | ||
31 | padding: 1ch 0; | ||
32 | } | ||
diff --git a/src/static/rss.xml b/src/static/rss.xml new file mode 100644 index 0000000..44617d8 --- /dev/null +++ b/src/static/rss.xml | |||
@@ -0,0 +1,27 @@ | |||
1 | <?xml version="1.0" encoding="UTF-8" ?> | ||
2 | <rss version="2.0"> | ||
3 | <channel> | ||
4 | <title>Acdw's Casa</title> | ||
5 | <description>My casa, in the middle of the web</description> | ||
6 | <link>https://acdw.casa</link> | ||
7 | <copyright>2022 Case Duckworth</copyright> | ||
8 | <lastBuildDate>2022-03-03</lastBuildDate> | ||
9 | <pubDate>2022-03-03</pubDate> | ||
10 | <ttl>1800</ttl> | ||
11 | |||
12 | <item> | ||
13 | <title>And we're live</title> | ||
14 | <description>Hi basement</description> | ||
15 | <link>https://acdw.casa/</link> | ||
16 | <pubDate>2022-03-03</pubDate> | ||
17 | </item> | ||
18 | |||
19 | <item> | ||
20 | <title>Good Choices License</title> | ||
21 | <description>A license for people</description> | ||
22 | <link>https://acdw.casa/gcl/</link> | ||
23 | <pubDate>2022-05-13</pubDate> | ||
24 | </item> | ||
25 | |||
26 | </channel> | ||
27 | </rss> | ||
diff --git a/tmpl.index.htm b/tmpl.index.htm new file mode 100644 index 0000000..dc90a4d --- /dev/null +++ b/tmpl.index.htm | |||
@@ -0,0 +1,16 @@ | |||
1 | $(sed 's#$(title)#acdw.casa#' _head.htm) | ||
2 | <header> | ||
3 | <h1>mi casa es su casa</h1> | ||
4 | </header> | ||
5 | <main> | ||
6 | <section id="welcome"> | ||
7 | $(htt _index.htm) | ||
8 | </section> | ||
9 | <section id="pages"> | ||
10 | <h2>pages here</h2> | ||
11 | <ul> | ||
12 | $(set -x;for p in ".tmp"/*.env; do . "$p"; print "<li><a href=\"$HTOUT\">$(title)</a></li>"; done) | ||
13 | </ul> | ||
14 | </section> | ||
15 | </main> | ||
16 | $(htt _foot.htm) | ||
diff --git a/tmpl.page.htm b/tmpl.page.htm new file mode 100644 index 0000000..4165681 --- /dev/null +++ b/tmpl.page.htm | |||
@@ -0,0 +1,8 @@ | |||
1 | $(htt _head.htm) | ||
2 | <header> | ||
3 | <h1>$(title)</h1> | ||
4 | </header> | ||
5 | <main> | ||
6 | $(body) | ||
7 | </main> | ||
8 | $(htt _foot.htm) | ||