aboutsummaryrefslogtreecommitdiff
path: root/v2/src
diff options
context:
space:
mode:
authorEuAndreh <eu@euandre.org>2023-04-05 16:14:00 -0300
committerEuAndreh <eu@euandre.org>2023-04-05 16:14:00 -0300
commit24e24b49fb6375189cfa527a113eb965087a293a (patch)
treefc75f8267a22f6473432ee6b07c4013561c303dc /v2/src
parentv2: Recove h[2-6] anchor link and icon (diff)
downloadeuandre.org-24e24b49fb6375189cfa527a113eb965087a293a.tar.gz
euandre.org-24e24b49fb6375189cfa527a113eb965087a293a.tar.xz
v2: Support Atom feeds and collection translations
Diffstat (limited to 'v2/src')
-rwxr-xr-xv2/src/bin/absolute2
-rwxr-xr-xv2/src/bin/collections69
-rwxr-xr-xv2/src/bin/conf (renamed from v2/src/development/genconf.sh)42
-rwxr-xr-xv2/src/bin/feed91
-rwxr-xr-xv2/src/bin/html (renamed from v2/src/development/genhtml.sh)21
-rwxr-xr-xv2/src/bin/lang-for73
-rwxr-xr-xv2/src/bin/langs69
-rwxr-xr-xv2/src/bin/makemake142
-rwxr-xr-xv2/src/bin/security-txt (renamed from v2/src/development/security-txt.sh.in)24
-rwxr-xr-xv2/src/bin/url-for30
-rwxr-xr-xv2/src/bin/xmlentry81
-rw-r--r--v2/src/content/en/about.md (renamed from v2/src/content/about.md)6
-rw-r--r--v2/src/content/en/pastebins/raku-tuple-type-annotation.md (renamed from v2/src/content/pastebins/raku-tuple-type-annotation.md)6
-rw-r--r--v2/src/content/en/pastebins/sicp-exercise-3-19.md (renamed from v2/src/content/pastebins/sicp-exercise-3-19.md)6
-rw-r--r--v2/src/content/en/tils/lisp-three-way-conditional.md (renamed from v2/src/content/tils/lisp-three-way-conditional.md)6
-rw-r--r--v2/src/content/favicon.icobin0 -> 1150 bytes
-rw-r--r--v2/src/content/pt/pastebins/exercicios-sicp-e-19.md103
-rw-r--r--v2/src/content/pt/sobre.md9
-rw-r--r--v2/src/lib.sh (renamed from v2/src/development/lib.sh)0
-rw-r--r--v2/src/lib/base.conf (renamed from v2/src/lib/base-conf.in)5
-rw-r--r--v2/src/lib/entry.xml22
-rw-r--r--v2/src/lib/feed.xml15
22 files changed, 679 insertions, 143 deletions
diff --git a/v2/src/bin/absolute b/v2/src/bin/absolute
index 6434219..ecf5a64 100755
--- a/v2/src/bin/absolute
+++ b/v2/src/bin/absolute
@@ -62,6 +62,6 @@ done
shift $((OPTIND - 1))
-. src/lib/base-conf
+. src/lib/base.conf
printf 'https://%s%s' "$domain" "$(cat)"
diff --git a/v2/src/bin/collections b/v2/src/bin/collections
new file mode 100755
index 0000000..1df0c39
--- /dev/null
+++ b/v2/src/bin/collections
@@ -0,0 +1,69 @@
+#!/bin/sh
+set -eu
+
+usage() {
+ cat <<-'EOF'
+ Usage:
+ collections
+ collections -h
+ EOF
+}
+
+help() {
+ cat <<-'EOF'
+
+
+ Options:
+ -h, --help show this message
+
+
+ List the registered collections to STDOUT.
+
+ This is done by emiting the content of the "$COLLECTIONS"
+ environment variable.
+
+
+ Examples:
+
+ Just run it:
+
+ $ collections
+ tils
+ pastebins
+ EOF
+}
+
+
+for flag in "$@"; do
+ case "$flag" in
+ --)
+ break
+ ;;
+ --help)
+ usage
+ help
+ exit
+ ;;
+ *)
+ ;;
+ esac
+done
+
+while getopts 'h' flag; do
+ case "$flag" in
+ h)
+ usage
+ help
+ exit
+ ;;
+ *)
+ usage >&2
+ exit 2
+ esac
+done
+shift $((OPTIND - 1))
+
+
+echo "$COLLECTIONS" |
+ tr ' ' '\n' |
+ grep .
diff --git a/v2/src/development/genconf.sh b/v2/src/bin/conf
index f9dfc14..ac02d98 100755
--- a/v2/src/development/genconf.sh
+++ b/v2/src/bin/conf
@@ -5,8 +5,8 @@ set -eu
usage() {
cat <<-'EOF'
Usage:
- src/development/genconf.sh FILENAME
- src/development/genconf.sh -h
+ conf FILENAME
+ conf -h
EOF
}
@@ -28,7 +28,7 @@ help() {
Get the "frontmatter" of src/f.conf:
- $ src/development/genconf.sh src/f.md > src/f.conf
+ $ conf src/f.md > src/f.conf
EOF
}
@@ -63,7 +63,7 @@ while getopts 'h' flag; do
done
shift $((OPTIND - 1))
-. src/development/lib.sh
+. src/lib.sh
FILENAME="${1:-}"
eval "$(assert_arg "$FILENAME" 'FILENAME')"
@@ -73,7 +73,7 @@ escape() {
sed 's|\([`"$]\)|\\\1|g'
}
-tee "$FILENAME".tmp < src/lib/base-conf
+tee "$FILENAME".tmp < src/lib/base.conf
DELIMITER=0
while read -r line; do
if [ "$line" = '---' ]; then
@@ -95,6 +95,11 @@ done < "$FILENAME" | tee -a "$FILENAME".tmp
. "$FILENAME".tmp
rm -f "$FILENAME".tmp
+
+lang="$(lang-for "$FILENAME")"
+export lang
+printf 'export lang="%s"\n' "$lang"
+
cat src/lib/base."${lang:?}".conf
# shellcheck source=/dev/null
. src/lib/base."$lang".conf
@@ -104,19 +109,30 @@ if [ -z "${title:-}" ]; then
fi
if [ -n "${date:-}" ]; then
- formatted_date="$(LANG="$lang" date -d "${date:?}" +"${date_fmt:?}")"
+ date_iso="$(date -ud "${date:?}" -Is)"
+ printf 'export date_iso="%s"\n' "$date_iso"
+
+ formatted_date="$(LANG="$lang" date -ud "${date:?}" +"${date_fmt:?}")"
export formatted_date
printf 'export date_html="%s"\n' "$(envsubst < src/lib/date."$lang".html | escape)"
+
+ echo "${FILENAME%.md}.xmlentry" > "$(dirname "$FILENAME")/$date_iso.sortdata"
+ touch "${FILENAME%.md}.sortref"
fi
if [ -n "${update:-}" ]; then
- formatted_update="$(LANG="$lang" date -d "${update:?}" +"${date_fmt:?}")"
+ update_iso="$(date -ud "${update:?}" -Is)"
+ printf 'export update_iso="%s"\n' "$update_iso"
+
+ formatted_update="$(LANG="$lang" date -ud "${update:?}" +"${date_fmt:?}")"
export formatted_update
printf 'export update_html="%s"\n' "$(envsubst < src/lib/update."$lang".html | escape)"
+
+ printf 'export update_xml=" <updated>%s</updated>"\n' "$update_iso"
fi
-url_part="$(printf '%s' "${FILENAME%.md}.html" | sed 's|^src/content/||')"
+url_part="$(printf '%s' "${FILENAME%.md}.html" | sed "s|^$CONTENT_PREFIX||")"
title_uri="$(uri "$title")"
printf 'export title_html="%s"\n' "$(printf '%s' "$title" | htmlesc | escape)"
@@ -127,13 +143,13 @@ printf 'export mailto_uri="%s%s"\n' "${mailto_uri_prefix:?}" "$title_uri"
printf 'export discussions_url="%s%s"\n' "${discussions_url_prefix:?}" "$title_uri"
printf 'export sourcecode_url="%s%s"\n' "${sourcecode_url_prefix:?}" "$FILENAME"
-printf 'export style_url="%s"\n' "$(url-for -g 'style.css')"
-printf 'export favicon_url="%s"\n' "$(url-for -g 'favicon.svg')"
-printf 'export pubkey_url="%s"\n' "$(url-for -g 'public.asc.txt')"
+printf 'export style_url="%s"\n' "$(url-for 'style.css')"
+printf 'export favicon_url="%s"\n' "$(url-for 'favicon.svg')"
+printf 'export pubkey_url="%s"\n' "$(url-for 'public.asc.txt')"
-for f in src/content/img/*.svg; do
+for f in "$CONTENT_PREFIX"/img/*.svg; do
name="$(basename "$f" .svg | sed 's|-|_|g')"
- printf 'export icon_%s_url="%s"\n' "$name" "$(url-for -g "img/$(basename "$f")")"
+ printf 'export icon_%s_url="%s"\n' "$name" "$(url-for "img/$(basename "$f")")"
done
# FIXME: special treatment of root
diff --git a/v2/src/bin/feed b/v2/src/bin/feed
new file mode 100755
index 0000000..96c40a6
--- /dev/null
+++ b/v2/src/bin/feed
@@ -0,0 +1,91 @@
+#!/bin/sh
+set -eu
+
+usage() {
+ cat <<-'EOF'
+ Usage:
+ feed FILENAME
+ feed -h
+ EOF
+}
+
+help() {
+ cat <<-'EOF'
+
+
+ Options:
+ -h, --help show this message
+
+ FILENAME the target feed to be generated
+
+
+ Generate FILENAME as an Atom feed. The collection type and
+ language are inferred by the name of FILENAME.
+
+
+ Examples:
+
+ Generate a feed for TILs:
+
+ $ feed src/en/feeds/til.xml
+ EOF
+}
+
+
+for flag in "$@"; do
+ case "$flag" in
+ --)
+ break
+ ;;
+ --help)
+ usage
+ help
+ exit
+ ;;
+ *)
+ ;;
+ esac
+done
+
+while getopts 'h' flag; do
+ case "$flag" in
+ h)
+ usage
+ help
+ exit
+ ;;
+ *)
+ usage >&2
+ exit 2
+ ;;
+ esac
+done
+shift $((OPTIND - 1))
+
+. src/lib.sh
+
+FILENAME="${1:-}"
+eval "$(assert_arg "$FILENAME" 'FILENAME')"
+
+
+COLLECTION="$(basename "$FILENAME" '.xml')"
+LANGUAGE="$(lang-for "$FILENAME")"
+DIR="$(dirname "$(dirname "$FILENAME")")/$COLLECTION"
+
+
+. src/lib/base.conf
+# shellcheck source=/dev/null
+. src/lib/base."$LANGUAGE".conf
+
+now="$(date -uIs)"
+url="$(url-for "${FILENAME#"$CONTENT_PREFIX"}" | absolute)"
+site_name_html="$(htmlesc "${site_name:?}")"
+export now url site_name_html
+
+
+mkdir -p "$(dirname "$FILENAME")"
+{
+ envsubst < src/lib/feed.xml
+ find "$DIR"/*.sortdata | sort -nr | xargs cat | xargs cat
+ printf '</feed>\n'
+} > "$FILENAME"
diff --git a/v2/src/development/genhtml.sh b/v2/src/bin/html
index 1b2718a..7e6809c 100755
--- a/v2/src/development/genhtml.sh
+++ b/v2/src/bin/html
@@ -4,34 +4,29 @@ set -eu
usage() {
cat <<-'EOF'
Usage:
- genhtml.sh FILENAME
- genhtml.sh -h
+ html FILENAME
+ html -h
EOF
}
help() {
cat <<-'EOF'
+
Options:
-h, --help show this message
- FILENAME the name of the input file, to also be used as
- URL
+ FILENAME the name of the input file .md file
Process the FILENAME, and generate a full HTML page.
- The FILENAME is used to infer the output URL, by removing the
- `src/content/` prefix, and replacing the trailing `.md` with
- `.html`. This URL is used to build the self-referencing
- "canonical" link, extracting plaintext snippets, etc.
-
Examples:
Generate the HTML for a pastebin:
- $ sh genhtml.sh src/content/a-paste.md > src/content/a-paste.html
+ $ html src/a-paste.md > src/a-paste.html
EOF
}
@@ -66,7 +61,7 @@ while getopts 'h' flag; do
done
shift $((OPTIND - 1))
-. src/development/lib.sh
+. src/lib.sh
FILENAME="${1:-}"
eval "$(assert_arg "$FILENAME" 'FILENAME')"
@@ -118,7 +113,7 @@ markdown_to_html() {
extract_plaintext_snippets() {
SNIPPETS="${FILENAME%.md}.snippets"
- rm -f "$SNIPPETS"
+ printf '' > "$SNIPPETS"
F="$(mkstemp)"
cat > "$F"
(
@@ -220,5 +215,5 @@ emit_body() {
}
envsubst < src/lib/preamble.html
-emit_body
+emit_body | tee "${FILENAME%.md}.htmlbody"
envsubst < src/lib/postamble.html
diff --git a/v2/src/bin/lang-for b/v2/src/bin/lang-for
new file mode 100755
index 0000000..f7c57a9
--- /dev/null
+++ b/v2/src/bin/lang-for
@@ -0,0 +1,73 @@
+#!/bin/sh
+set -eu
+
+usage() {
+ cat <<-'EOF'
+ Usage:
+ lang-for FILE
+ lang-for -h
+ EOF
+}
+
+help() {
+ cat <<-'EOF'
+
+
+ Options:
+ -h, --help show this message
+
+ FILE the path of the file to get the language for
+
+
+ Say the language of the given file, using the path of FILE.
+
+
+ Examples:
+
+ Get "en" for "src/en/some-pt.md":
+
+ $ lang-for src/en/some-pt.md
+ en
+ EOF
+}
+
+
+for flag in "$@"; do
+ case "$flag" in
+ --)
+ break
+ ;;
+ --help)
+ usage
+ help
+ exit
+ ;;
+ *)
+ ;;
+ esac
+done
+
+while getopts 'h' flag; do
+ case "$flag" in
+ h)
+ usage
+ help
+ exit
+ ;;
+ *)
+ usage >&2
+ exit 2
+ ;;
+ esac
+done
+shift $((OPTIND - 1))
+
+. src/lib.sh
+
+
+FILE="${1:-}"
+eval "$(assert_arg "$FILE" 'FILE')"
+
+
+echo "${FILE#"$CONTENT_PREFIX"/}" |
+ cut -d/ -f1
diff --git a/v2/src/bin/langs b/v2/src/bin/langs
new file mode 100755
index 0000000..8e8aa63
--- /dev/null
+++ b/v2/src/bin/langs
@@ -0,0 +1,69 @@
+#!/bin/sh
+set -eu
+
+usage() {
+ cat <<-'EOF'
+ Usage:
+ langs
+ langs -h
+ EOF
+}
+
+help() {
+ cat <<-'EOF'
+
+
+ Options:
+ -h, --help show this message
+
+
+ List the supported languages, including english, to STDOUT.
+
+ This is done in the same way that po4a(1) does it: by listing
+ the po/*.po files, and getting the name from it.
+
+
+ Examples:
+
+ Just run it:
+
+ $ langs
+ en
+ pt
+ EOF
+}
+
+
+for flag in "$@"; do
+ case "$flag" in
+ --)
+ break
+ ;;
+ --help)
+ usage
+ help
+ exit
+ ;;
+ *)
+ ;;
+ esac
+done
+
+while getopts 'h' flag; do
+ case "$flag" in
+ h)
+ usage
+ help
+ exit
+ ;;
+ *)
+ usage >&2
+ exit 2
+ esac
+done
+shift $((OPTIND - 1))
+
+
+echo po/en.po po/*.po |
+ tr ' ' '\n' |
+ sed 's|^po/\(.*\)\.po$|\1|'
diff --git a/v2/src/bin/makemake b/v2/src/bin/makemake
index e95a040..fdd0e68 100755
--- a/v2/src/bin/makemake
+++ b/v2/src/bin/makemake
@@ -64,84 +64,110 @@ varlist() {
printf '\n'
}
-html_deps() {
- "$@" | sed 's/^\(.*\)\.md$/\1.conf \1.content: \1.md/'
- "$@" | sed 's/^\(.*\)\.md$/\1.snippets \1.html: \1.conf \1.content/'
- printf '\n'
-}
-
-
-content_mds() {
- {
- if [ "$r" = 'pages' ]; then
- echo src/content/*.md
- else
- echo src/content/"$r"/*.md
- fi
- } | tr ' ' '\n'
-}
-
-RESOURCES='
-pages
-pastebins
-tils
-'
EXTENSIONS='
-.md
.conf
.content
.html
.snippets
+.htmlbody
'
-for r in $RESOURCES; do
- content_mds "$r" | varlist "$r".md
- for e in $EXTENSIONS; do
- if [ "$e" = '.md' ]; then
- continue
+COLL_EXTENSIONS='
+.sortref
+.xmlentry
+'
+
+page_ext_filter="^($(echo "$COLL_EXTENSIONS" |
+ tr ' ' '\n' |
+ grep . |
+ paste -sd'|'
+))\$"
+
+
+extensions() {
+ echo "$EXTENSIONS" "$COLL_EXTENSIONS" "$@" |
+ tr ' ' '\n' |
+ grep .
+}
+
+
+printf '.POSIX:\n\n\n'
+for lang in $(langs); do
+ for c in pages $(collections); do
+ if [ "$c" = 'pages' ]; then
+ filter="$page_ext_filter"
+ dir="$CONTENT_PREFIX/$lang"
+ else
+ filter='^$'
+ dir="$CONTENT_PREFIX/$lang/$c"
fi
- # shellcheck disable=2016
- printf '%s%s = $(%s.md:.md=%s)\n' "$r" "$e" "$r" "$e"
- done
- printf '%s =' "$r"
- for e in $EXTENSIONS; do
- if [ "$e" = '.md' ]; then
+
+ mds() {
+ # find "$dir"/*.md # FIXME
+ find "$dir"/*.md 2>/dev/null
+ }
+
+ exts() {
+ extensions | grep -Ev "$filter"
+ }
+
+ mds | varlist "$c.$lang.md"
+ exts | sed "s|^\(.*\)\$|$c.$lang\1 = \$($c.$lang.md:.md=\1)|"
+ exts | sed "s|^\(.*\)\$|\$($c.$lang\1)|" | varlist "$c.$lang"
+
+ mds | sed 's/^\(.*\)\.md$/\1.conf \1.content: \1.md/'
+ mds | sed 's/^\(.*\)\.md$/\1.snippets \1.htmlbody \1.html: \1.conf \1.content/'
+ if [ "$c" = 'pages' ]; then
continue
fi
- # shellcheck disable=2016
- printf ' $(%s%s)' "$r" "$e"
+
+ mds | sed 's/^\(.*\)\.md$/\1.sortref: \1.md/'
+ mds | sed 's/^\(.*\)\.md$/\1.xmlentry: \1.html/'
+
+ echo "$CONTENT_PREFIX/$lang/feeds/$c.xml: \$($c.$lang.xmlentry)"
+
+ printf '\n\n'
done
- printf '\n'
- html_deps content_mds "$r"
- printf '\n'
-done
+ for e in $(extensions); do
+ {
+ if ! printf '%s\n' "$e" | grep -qE "$page_ext_filter"; then
+ echo pages
+ fi
+ collections
+ } |
+ sed "s|^\(.*\)\$|\$(\1.$lang$e)|" |
+ varlist "all-generated.$lang$e"
+ done
-all_resources() {
- echo "$RESOURCES" | tr ' ' '\n' | grep .
-}
+ collections |
+ sed "s|^\(.*\)\$|$CONTENT_PREFIX/$lang/feeds/\1.xml|" |
+ varlist "all-generated.$lang.xml"
-all_vars() {
- EXT="$1"
- # shellcheck disable=2016
- all_resources |
- sed 's|^|$(|' |
- sed "s|$|$EXT)|" |
- varlist all-generated"$EXT"
-}
+ extensions '.xml' |
+ sed "s|^\(.*\)\$|\$(all-generated.$lang\1)|" |
+ varlist "all-generated.$lang"
-for e in $EXTENSIONS; do
- all_vars "$e"
+ printf '\n'
+done
+
+for e in $(extensions .xml); do
+ langs |
+ sed "s|^\(.*\)\$|\$(all-generated.\1$e)|" |
+ varlist "all-generated$e"
done
-all_vars ''
+
+# shellcheck disable=2016
+langs |
+ sed 's|^\(.*\)$|$(all-generated.\1)|' |
+ varlist 'all-generated'
-git ls-files |
- grep -v '^src/content/' |
+git ls-files src/ |
+ grep -v ^"$CONTENT_PREFIX"/ |
varlist 'non-content'
-git ls-files src/content/ |
+git ls-files "$CONTENT_PREFIX"/ |
grep -v '\.md$' |
- grep -Ev "src/content/($(all_resources | paste -sd'|'))/" |
varlist 'static-content'
diff --git a/v2/src/development/security-txt.sh.in b/v2/src/bin/security-txt
index 8f6613f..7026969 100755
--- a/v2/src/development/security-txt.sh.in
+++ b/v2/src/bin/security-txt
@@ -4,8 +4,8 @@ set -eu
usage() {
cat <<-'EOF'
Usage:
- src/development/security-txt.sh
- src/development/security-txt.sh -h
+ security-txt
+ security-txt -h
EOF
}
@@ -25,7 +25,7 @@ help() {
Just run it:
- $ sh src/development/security-txt.sh > .well-known/security.txt
+ $ security-txt > .well-known/security.txt
EOF
}
@@ -62,21 +62,21 @@ shift $((OPTIND - 1))
EXPIRES="$(
- LANG=C.UTF-8 gpg --list-key eu@euandre.org |
+ LANG=C.UTF-8 gpg --list-key "$EMAIL" |
awk '/^pub/ { print substr($(NF), 1, 10) }'
)T00:00:00z"
-LANGS="en$(
- echo po/??.po |
- sed 's|\.po$||' |
- sed 's|^po/|, |' |
- paste -sd,
+LANGUAGES="$(
+ langs |
+ sed 's|^|, |' |
+ tr -d '\n' |
+ sed 's|^, ||'
)"
cat <<-EOF
- Contact: mailto:@EMAIL@
- Encryption: https://@DOMAIN@/public.asc.txt
+ Contact: mailto:$EMAIL
+ Encryption: $(url-for 'public.asc.txt' | absolute)
Expires: $EXPIRES
- Preferred-Languages: $LANGS
+ Preferred-Languages: $LANGUAGES
EOF
diff --git a/v2/src/bin/url-for b/v2/src/bin/url-for
index d4099bc..adaccd7 100755
--- a/v2/src/bin/url-for
+++ b/v2/src/bin/url-for
@@ -4,7 +4,7 @@ set -eu
usage() {
cat <<-'EOF'
Usage:
- url-for [-g] FILE
+ url-for FILE
url-for -h
EOF
}
@@ -13,7 +13,6 @@ help() {
cat <<-'EOF'
Options:
- -g global file, not specific to a single language
-h, --help show this message
FILE the path for the URL to be constructed
@@ -25,7 +24,7 @@ help() {
Examples:
- Get the URL for "about.html", when $base_url is "v2" and $lang is "en":
+ Get the URL for "en/about.html", when $base_url is "v2":
$ url-for 'about.html'
/v2/en/about.html
@@ -33,8 +32,8 @@ help() {
Get the URL for "static/favicon.svg", when $base_url is empty:
- $ url-for -g 'static/favicon.svg'
- /static/favicon.svg
+ $ url-for 'img/link.svg'
+ /img/link.svg
EOF
}
@@ -54,12 +53,8 @@ for flag in "$@"; do
esac
done
-GLOBAL=false
-while getopts 'gh' flag; do
+while getopts 'h' flag; do
case "$flag" in
- g)
- GLOBAL=true
- ;;
h)
usage
help
@@ -73,22 +68,19 @@ while getopts 'gh' flag; do
done
shift $((OPTIND - 1))
-. src/development/lib.sh
-
+. src/lib.sh
FILE="${1:-}"
+eval "$(assert_arg "$FILE" 'FILE')"
+
+
if [ "$FILE" = '/' ]; then
FILE=''
fi
-. src/lib/base-conf
+. src/lib/base.conf
# shellcheck source=/dev/null
. src/lib/base."${lang:?}".conf
-if [ "$GLOBAL" = true ]; then
- L=''
-else
- L="${lang:?}/"
-fi
-printf '%s%s%s' "${base_url:-/}" "$L" "$FILE"
+printf '%s%s' "${base_url:-/}" "$FILE"
diff --git a/v2/src/bin/xmlentry b/v2/src/bin/xmlentry
new file mode 100755
index 0000000..b0760ae
--- /dev/null
+++ b/v2/src/bin/xmlentry
@@ -0,0 +1,81 @@
+#!/bin/sh
+set -eu
+
+usage() {
+ cat <<-'EOF'
+ Usage:
+ xmlentry FILENAME
+ xmlentry -h
+ EOF
+}
+
+help() {
+ cat <<-'EOF'
+
+
+ Options:
+ -h, --help show this message
+
+ FILENAME the name of the input .md file
+
+
+ Process FILE, and generate an Atom feed entry.
+
+
+ Examples:
+
+ Generate the XML entry for a TIL:
+
+ $ xmlentry src/tils/a-til.md > src/tils/a-til.xml
+ EOF
+}
+
+
+for flag in "$@"; do
+ case "$flag" in
+ --)
+ break
+ ;;
+ --help)
+ usage
+ help
+ exit
+ ;;
+ *)
+ ;;
+ esac
+done
+
+while getopts 'h' flag; do
+ case "$flag" in
+ h)
+ usage
+ help
+ exit
+ ;;
+ *)
+ usage >&2
+ exit 2
+ ;;
+ esac
+done
+shift $((OPTIND - 1))
+
+. src/lib.sh
+
+FILENAME="${1:-}"
+eval "$(assert_arg "$FILENAME" 'FILENAME')"
+
+
+# shellcheck source=/dev/null
+. "${FILENAME%.md}.conf"
+
+envsubst < src/lib/entry.xml
+
+head -n1 < "${FILENAME%.md}.htmlbody" | htmlesc
+printf ' </summary>\n'
+printf ' <content type="html" xml:base="%s">\n' "${url:?}"
+
+htmlesc < "${FILENAME%.md}.htmlbody"
+printf ' </content>\n'
+printf ' </entry>\n'
diff --git a/v2/src/content/about.md b/v2/src/content/en/about.md
index b10f26b..1e39407 100644
--- a/v2/src/content/about.md
+++ b/v2/src/content/en/about.md
@@ -2,12 +2,6 @@
title: About
-layout: page
-
-lang: en
-
-ref: aboud
-
---
It's all about me, baby!
diff --git a/v2/src/content/pastebins/raku-tuple-type-annotation.md b/v2/src/content/en/pastebins/raku-tuple-type-annotation.md
index 3d5ff34..5877470 100644
--- a/v2/src/content/pastebins/raku-tuple-type-annotation.md
+++ b/v2/src/content/en/pastebins/raku-tuple-type-annotation.md
@@ -4,12 +4,6 @@ title: Raku tuple type annotation
date: 2019-12-29
-layout: post
-
-lang: en
-
-ref: raku-tuple-type-annotation
-
---
```perl
diff --git a/v2/src/content/pastebins/sicp-exercise-3-19.md b/v2/src/content/en/pastebins/sicp-exercise-3-19.md
index 8834889..3188dce 100644
--- a/v2/src/content/pastebins/sicp-exercise-3-19.md
+++ b/v2/src/content/en/pastebins/sicp-exercise-3-19.md
@@ -4,12 +4,6 @@ title: SICP exercise 3.19
date: 2021-09-02
-layout: post
-
-lang: en
-
-id: sicp-exercise-3-19
-
---
Some content here, before:
diff --git a/v2/src/content/tils/lisp-three-way-conditional.md b/v2/src/content/en/tils/lisp-three-way-conditional.md
index 81920c4..cd7a034 100644
--- a/v2/src/content/tils/lisp-three-way-conditional.md
+++ b/v2/src/content/en/tils/lisp-three-way-conditional.md
@@ -6,12 +6,6 @@ date: 2021-04-24 3
update: 2021-08-14
-layout: post
-
-lang: en
-
-ref: three-way-conditional-for-number-signs-on-lisp
-
---
A useful macro from Paul Graham's [On Lisp][on-lisp] book:
diff --git a/v2/src/content/favicon.ico b/v2/src/content/favicon.ico
new file mode 100644
index 0000000..8f2130a
--- /dev/null
+++ b/v2/src/content/favicon.ico
Binary files differ
diff --git a/v2/src/content/pt/pastebins/exercicios-sicp-e-19.md b/v2/src/content/pt/pastebins/exercicios-sicp-e-19.md
new file mode 100644
index 0000000..d4db88d
--- /dev/null
+++ b/v2/src/content/pt/pastebins/exercicios-sicp-e-19.md
@@ -0,0 +1,103 @@
+---
+
+title: SICP exercise 3.19
+
+date: 2021-09-02
+
+---
+
+Some content here, before:
+
+```scheme
+(define (cycle? l)
+ (define (rec l x)
+ (cond
+ ((null? x) false)
+ ((eq? l x) true)
+ (true (rec l (cdr x)))))
+ (rec l (cdr l)))
+```
+
+Sample interactive session:
+
+```scheme
+scheme@(guile-user)> (define true #t)
+scheme@(guile-user)> (define false #f)
+scheme@(guile-user)>
+(define (cycle? l)
+ (define (rec l x)
+ (cond
+ ((null? x) false)
+ ((eq? l x) true)
+ (true (rec l (cdr x)))))
+ (rec l (cdr l)))
+scheme@(guile-user)> (cycle? '(1 2 3))
+$9 = #f
+scheme@(guile-user)> (cycle? (make-cycle '(1 2 3)))
+$10 = #t
+```
+
+# An h1
+
+a list:
+
+1. one
+2. two
+3. three
+
+some content.
+
+- item
+- another
+- yet another
+
+## An h2
+
+Xablau:
+
+``` xupliu 1
+
+3 4
+
+
+
+
+
+dez ```
+
+Foi `wikiwiu`.
+
+a very long code block:
+
+```
+wef
+wef wef wef wef
+wef wef wef wef we fwef wef wef wef wef
+```
+
+Someone said:
+
+> Xablau, xupliu.
+
+### A repeated header ### A repeated header
+
+a big list:
+
+1. a
+1. a
+1. a
+1. a
+1. a
+1. a
+1. a
+1. a
+1. a
+1. a
+1. a
+1. a
+1. a
+1. a
+1. a
+1. a
+1. a
+1. a
diff --git a/v2/src/content/pt/sobre.md b/v2/src/content/pt/sobre.md
new file mode 100644
index 0000000..97eecf8
--- /dev/null
+++ b/v2/src/content/pt/sobre.md
@@ -0,0 +1,9 @@
+---
+
+title: About
+
+---
+
+It's all about me, baby!
+
+``` xablau ```
diff --git a/v2/src/development/lib.sh b/v2/src/lib.sh
index 9d183f9..9d183f9 100644
--- a/v2/src/development/lib.sh
+++ b/v2/src/lib.sh
diff --git a/v2/src/lib/base-conf.in b/v2/src/lib/base.conf
index 4ec09cb..319d08c 100644
--- a/v2/src/lib/base-conf.in
+++ b/v2/src/lib/base.conf
@@ -1,10 +1,9 @@
-export domain='@DOMAIN@'
-export email='@EMAIL@'
+export domain="$DOMAIN"
+export email="$EMAIL"
export base_url=''
export list_addr='~euandreh/public-inbox@lists.sr.ht'
export mailto_uri_prefix="mailto:$list_addr?Subject=Re%3A%20"
export discussions_url_prefix="https://lists.sr.ht/~euandreh/public-inbox?search="
export sourcecode_url_prefix="https://$domain/git/$domain/tree/"
export author='EuAndreh'
-export lang='en'
export pubkey_id='81F90EC3CD356060' # FIXME
diff --git a/v2/src/lib/entry.xml b/v2/src/lib/entry.xml
new file mode 100644
index 0000000..e4a47c7
--- /dev/null
+++ b/v2/src/lib/entry.xml
@@ -0,0 +1,22 @@
+ <entry xml:lang="$lang">
+ <title type="html">
+ $title_html
+ </title>
+ <link type="text/html" rel="alternative" href="$url" title="$title_html" />
+ <published>
+ $date_iso
+ </published>
+$update_xml
+ <id>
+ $url
+ </id>
+ <author>
+ <name>
+ $author
+ </name>
+ <email>
+ $email
+ </email>
+ </author>
+
+ <summary type="html">
diff --git a/v2/src/lib/feed.xml b/v2/src/lib/feed.xml
new file mode 100644
index 0000000..6fd82a4
--- /dev/null
+++ b/v2/src/lib/feed.xml
@@ -0,0 +1,15 @@
+<feed
+ xmlns="http://www.w3.org/2005/Atom"
+ xmlns:content="http://purl.org/rss/1.0/modules/content/"
+ xml:lang="$lang">
+ <link href="$url" rel="self" type="application/atom+xml" />
+ <link href="$homepage_url" rel="alternate" type="text/html" hreflang="$lang" />
+ <title>$site_name_html</title>
+ <subtitle>{{ site.t[include.kind].feed.title[include.lang] | smartify | xml_escape }}</subtitle>
+ <id>$url</id>
+ <updated>$now</updated>
+
+ <author>
+ <name>$author</name>
+ <email>$email</email>
+ </author>