summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rwxr-xr-xsrc/conf217
-rwxr-xr-xsrc/feed60
-rwxr-xr-xsrc/feedentry (renamed from src/xmlentry)25
-rwxr-xr-xsrc/html307
-rwxr-xr-xsrc/htmlbody26
-rwxr-xr-xsrc/indexbody24
-rwxr-xr-xsrc/indexentry20
-rwxr-xr-xsrc/mkwb.in4
-rwxr-xr-xsrc/snippets27
-rwxr-xr-xsrc/sortdata16
10 files changed, 498 insertions, 228 deletions
diff --git a/src/conf b/src/conf
index 6aa6761..d132a34 100755
--- a/src/conf
+++ b/src/conf
@@ -1,30 +1,207 @@
#!/bin/sh
-set -eu
+set -euo pipefail
usage() {
- echo 'Usage: conf FILENAME'
+ echo 'Usage: conf BASECONF [GLOBALCONF FILENAME.adoc]'
}
-FILENAME="${1:-}"
+
+needs() {
+ if [ -z "${1:-}" ]; then
+ printf '%s\n' "$2" >&2
+ exit 1
+ fi
+}
+
+DATE_I='+%Y-%m-%d'
+DATE_Is="${DATE_I}T%H:%M:%S%:z"
+datex() {
+ # date(1), plus non-POSIX -d option
+ DATESTR="$1"
+ shift
+ date -d "$DATESTR" "$@"
+}
+
+dateiso() {
+ datex "$1" -u "$DATE_Is"
+}
+
+BASECONF="${1:-}"
+GLOBALCONF="${2:-}"
+FILENAME="${3:-}"
+eval "$(assert-arg -- "$BASECONF" 'BASECONF')"
+. "$(realpath -- "$BASECONF")"
+
+
+needs "${url_pre:-}" 'Missing required $url_pre (e.g. https://example.com)'
+needs "${site_name:-}" 'Missing required $site_name'
+needs "${feed_title:-}" 'Missing required $feed_title'
+needs "${feed_url:-}" 'Missing required $feed_url'
+needs "${feed_alternate_url:-}" 'Missing required $feed_alternate_url'
+
+needs "${list_addr:-}" 'Missing required $list_addr'
+needs "${discussions_url_prefix:-}" 'Missing required $discussions_url_prefix'
+
+needs "${email:-}" 'Missing required $email'
+needs "${author:-}" 'Missing required $author'
+needs "${sourcecode_url:-}" 'Missing required $sourcecode_url'
+needs "${sourcecode_url_prefix:-}" 'Missing required $sourcecode_url_prefix'
+
+
+if [ -z "$GLOBALCONF" ]; then
+ now_iso="$(dateiso "@${SOURCE_DATE_EPOCH:-$(date '+%s')}" | shesc)"
+ feed_title_html="$(printf '%s\n' "$feed_title" | htmlesc | shesc)"
+ site_name_html="$( printf '%s\n' "$site_name" | htmlesc | shesc)"
+ if [ -z "${logo_alt:-}" ]; then
+ logo_alt='The website logo'
+ fi
+ logo_alt="$(printf '%s\n' "$logo_alt" | htmlesc | shesc)"
+
+ cat <<-EOF
+ export now_iso="$now_iso"
+ export feed_title_html="$feed_title_html"
+ export site_name_html="$site_name_html"
+ export feed_url_absolute="$url_pre/$feed_url"
+ export feed_alternate_url_absolute="$url_pre/$feed_alternate_url"
+ export logo_alt="$logo_alt"
+ EOF
+ exit
+fi
+
+eval "$(assert-arg -- "$BASECONF" 'BASECONF')"
eval "$(assert-arg -- "$FILENAME" 'FILENAME')"
+. "$(realpath -- "$GLOBALCONF")"
+
+trap 'rm -f -- "$FILENAME".embedded-config' EXIT
+
+{
+ if head -n1 -- "$FILENAME" | grep -q '^////$'; then
+ awk 'sep > 1 {exit}; /^\/{4}$/ { sep++; next } { print }' \
+ "$FILENAME"
+ fi
+} > "$FILENAME".embedded-config
+. "$(realpath -- "$FILENAME".embedded-config)"
+
+is_article() {
+ printf '%s\n' "$FILENAME" | grep -qE \
+ "^${root_dir}[-a-zA-Z0-9/]*/[0-9]{4}/[0-9]{2}/[0-9]{2}/[-A-Za-z0-9]+\.adoc$"
+ #^ src /blog/d/a /1970 /01 /01/ /some-file-N4me.adoc
+}
+
+base_url() {
+ # src/sub/dirs/file.txt -> ../..
+ # src/file.txt -> .
+ printf '%s/\n' "$(dirname -- "$UNPREFIXED")" |
+ sed \
+ -e 's|[^/]*/|../|g' \
+ -e 's|/$||' \
+ -e 's|^\.\.$|.|'
+}
+
+last3dirnames() {
+ dirname -- "$UNPREFIXED" | tr '/' '\n' | tail -n3 | paste -sd-
+}
+
+datefmt() {
+ LANG=en_GB.UTF-8 datex "$1" -u '+%B %-d, %Y'
+}
+
+
+if [ -z "${root_dir:-}" ]; then
+ root_dir="$(dirname -- "$BASECONF")"
+fi
+root_dir="${root_dir%/}"
+if [ -z "${img_dir:-}" ]; then
+ img_dir=img
+fi
+img_dir="${img_dir%/}"
-date="$(dirname "${FILENAME#src/}" | tr '/' '-')"
-date_iso="$(date -ud "${date:?}" -Is)" # FIXME: non POSIX
-printf 'export date_iso="%s"\n' "$date_iso"
-
-cat <<-'EOF'
- 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 url='url1'
- export site_name='site_name1'
- export feed_article_title='Articles from papo.im'
- export lang=en
+UNPREFIXED="${FILENAME#$root_dir/}"
+
+cat "$BASECONF" "$GLOBALCONF"
+
+date_iso=
+date_formatted=
+updatedat_iso=
+updatedat_formatted=
+if is_article; then
+ date_iso="$(dateiso "$(last3dirnames)" | shesc)"
+ date_formatted="$(datefmt "$date_iso" | shesc)"
+ if [ -n "${updatedat:-}" ]; then
+ updatedat_iso="$(dateiso "$updatedat" | shesc)"
+ updatedat_formatted="$(datefmt "$updatedat_iso" | shesc)"
+ fi
+fi
+
+BASE_URL="$(base_url)"
+TITLE_RAW="$(cat -- "$FILENAME" | grep '^= .*' | head -n1 | cut -d' ' -f2-)"
+TITLEFULL_RAW="$TITLE_RAW | $site_name"
+
+if [ -z "${css_url:-}" ]; then
+ css_url="$BASE_URL/style.css"
+fi
+if [ -z "${atom_url:-}" ]; then
+ atom_url="$BASE_URL/atom.xml"
+fi
+if [ -z "${atomicon_url:-}" ]; then
+ needs "${img_dir:-}" 'Define either $atomicon_url or $img_dir'
+ atomicon_url="$BASE_URL/$img_dir/atom.svg"
+fi
+if [ -z "${favicon_url:-}" ]; then
+ needs "${img_dir:-}" 'Define either $favicon_url or $img_dir'
+ favicon_url="$BASE_URL/$img_dir/favicon.svg"
+fi
+if [ -z "${logo_url_prefix:-}" ]; then
+ needs "${img_dir:-}" 'Define either $logo_url_prefix or $img_dir'
+ logo_url_prefix="$BASE_URL/$img_dir/logo"
+fi
+if [ -z "${envelopeicon_url_prefix:-}" ]; then
+ needs "${img_dir:-}" 'Define either $envelopeicon_url_prefix or $img_dir'
+ envelopeicon_url_prefix="$BASE_URL/$img_dir/envelope"
+fi
+
+title_uri="$(printf '%s' "$TITLE_RAW" | uri)"
+comment_url="$(printf 'mailto:%s?Subject=Re%%3A%%20%s\n' "$list_addr" "$title_uri" | shesc)"
+discussions_url="$(printf '%s%s\n' "$discussions_url_prefix" "$title_uri" | shesc)"
+
+url="$(printf '%s\n' "${UNPREFIXED%.adoc}.html" | shesc)"
+
+css_url="$( printf '%s\n' "$css_url" | shesc)"
+atom_url="$( printf '%s\n' "$atom_url" | shesc)"
+atomicon_url="$( printf '%s\n' "$atomicon_url" | shesc)"
+favicon_url="$( printf '%s\n' "$favicon_url" | shesc)"
+logo_url_prefix="$( printf '%s\n' "$logo_url_prefix" | shesc)"
+envelopeicon_url_prefix="$(printf '%s\n' "$envelopeicon_url_prefix" | shesc)"
+
+source_path="$(printf '%s\n' "$FILENAME" | shesc)"
+base_url_prefix="$(printf '%s\n' "$BASE_URL" | shesc)"
+title="$( printf '%s\n' "$TITLE_RAW" | shesc)"
+title_html="$( printf '%s\n' "$TITLE_RAW" | htmlesc | shesc)"
+titlefull="$( printf '%s\n' "$TITLEFULL_RAW" | shesc)"
+titlefull_html="$(printf '%s\n' "$TITLEFULL_RAW" | htmlesc | shesc)"
+cat <<-EOF
+ export css_url="$css_url"
+ export atom_url="$atom_url"
+ export atomicon_url="$atomicon_url"
+ export favicon_url="$favicon_url"
+ export logo_url_prefix="$logo_url_prefix"
+ export envelopeicon_url_prefix="$envelopeicon_url_prefix"
+ export source_path="$source_path"
+ export url="$url"
+ export url_absolute="$url_pre/$url"
+ export base_url_prefix="$base_url_prefix"
+ export title="$title"
+ export title_html="$title_html"
+ export titlefull="$titlefull"
+ export titlefull_html="$titlefull_html"
+ export date_iso="$date_iso"
+ export date_formatted="$date_formatted"
+ export updatedat_iso="$updatedat_iso"
+ export updatedat_formatted="$updatedat_formatted"
+ export comment_url="$comment_url"
+ export discussions_url="$discussions_url"
EOF
+
+cat "$FILENAME".embedded-config
diff --git a/src/feed b/src/feed
index f202ba6..aa42899 100755
--- a/src/feed
+++ b/src/feed
@@ -1,52 +1,52 @@
#!/bin/sh
-set -eu
+set -euo pipefail
+
usage() {
- echo 'Usage: feed FILENAME'
+ echo 'Usage: feed BASECONF GLOBALCONF FILENAME.sortdata...'
}
-FILENAME="${1:-}"
-eval "$(assert-arg -- "$FILENAME" 'FILENAME')"
-
+BASECONF="${1:-}"
+GLOBALCONF="${2:-}"
+FILES="${3:-}"
+eval "$(assert-arg -- "$BASECONF" 'BASECONF')"
+eval "$(assert-arg -- "$GLOBALCONF" 'GLOBALCONF')"
+eval "$(assert-arg -- "$FILES" 'FILENAME.sortdata...')"
+. "$(realpath -- "$BASECONF")"
+. "$(realpath -- "$GLOBALCONF")"
+shift
+shift
-absolute() {
- printf 'https://domain-here.com/%s' "$(cat -)"
-}
-feed_article_title=''
-site_name=' '
-lang=en
-now="$(date -uIs)"
-url_absolute="$(printf '%s' "${FILENAME#src/}" | absolute)"
-site_name_html="$(htmlesc "${site_name:?}")"
-collection=article
-collection_url_absolute="$(printf '%s' ${lang:?}/ | absolute)"
-feed_title_html="$(eval "echo \"\$feed_${collection}_title\"" | htmlesc)"
-export now url_absolute site_name_html collection_url_absolute feed_title_html
-
-DIR="$(dirname "$FILENAME")"
-
-author=
-email=
-cat <<EOF
+pre() {
+ cat <<EOF | sed '/^$/d'
<feed
xmlns="http://www.w3.org/2005/Atom"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
- xml:lang="$lang">
- <link href="$url_absolute" rel="self" type="application/atom+xml" />
- <link href="$collection_url_absolute" rel="alternate" type="text/html" hreflang="$lang" />
+ xml:lang="en">
+ <link rel="self" type="application/atom+xml" href="$feed_url_absolute" />
+ <link rel="alternate" type="text/html" href="$feed_alternate_url_absolute" hreflang="en" />
<title>$site_name_html</title>
<subtitle>$feed_title_html</subtitle>
- <id>$url_absolute</id>
- <updated>$now</updated>
+ <id>$feed_url_absolute</id>
+ <updated>$now_iso</updated>
<author>
<name>$author</name>
<email>$email</email>
</author>
EOF
+}
+
+post() {
+ printf '</feed>\n'
+}
+
+pre
find "$@" |
xargs cat |
sort -nr |
+ xargs cat |
+ sed 's/\.conf$/.feedentry/' |
xargs cat
-printf '</feed>\n'
+post
diff --git a/src/xmlentry b/src/feedentry
index c2458d1..6299e6f 100755
--- a/src/xmlentry
+++ b/src/feedentry
@@ -1,21 +1,26 @@
#!/bin/sh
-set -eu
+set -euo pipefail
usage() {
- echo 'Usage: xmlentry FILENAME'
+ echo 'Usage: feedentry FILENAME.htmlbody'
}
FILENAME="${1:-}"
-eval "$(assert-arg -- "$FILENAME" 'FILENAME')"
-. "${FILENAME%.*}.conf"
+eval "$(assert-arg -- "$FILENAME" 'FILENAME.htmlbody')"
+. "$(realpath -- "${FILENAME%.*}.conf")"
-title_html=
-url_absolute=
update_xml=
-cat <<EOF
- <entry xml:lang="$lang">
+if [ -n "${updated_at:-}" ]; then
+ update_iso="$(date -ud "$updated_at" -Is)"
+ update_xml=" <updated>
+ $update_iso
+ </updated>"
+fi
+
+cat <<EOF | sed '/^$/d'
+ <entry xml:lang="en">
<title type="html">
$title_html
</title>
@@ -39,10 +44,10 @@ $update_xml
<summary type="html">
EOF
-head -n1 < "${FILENAME%.*}.htmlbody" | htmlesc
+head -n5 < "$FILENAME" | htmlesc
printf ' </summary>\n'
printf ' <content type="html" xml:base="%s">\n' "${url:?}"
-htmlesc < "${FILENAME%.*}.htmlbody"
+htmlesc < "$FILENAME"
printf ' </content>\n'
printf ' </entry>\n'
diff --git a/src/html b/src/html
index 007fcc2..3e100cb 100755
--- a/src/html
+++ b/src/html
@@ -1,174 +1,165 @@
#!/bin/sh
-set -eu
+set -euo pipefail
+
usage() {
- echo 'Usage: html FILENAME'
+ echo 'Usage: html FILENAME.htmlbody'
}
FILENAME="${1:-}"
-eval "$(assert-arg -- "$FILENAME" 'FILENAME')"
-
-. "${FILENAME%.*}.conf"
-
-#
-# Utility functions
-#
-
-INDENT=' '
-markdown_to_html() {
- md2html | awk -vINDENT="$INDENT" '
- BEGIN {
- in_block = 0
- }
-
- {
- if (in_block == 0) {
- printf "%s", INDENT
- }
- print
- }
-
- /^<\/code><\/pre>$/ {
- in_block = 0
- }
-
- /^<pre><code/ {
- in_block = 1
- }
- '
+eval "$(assert-arg -- "$FILENAME" 'FILENAME.htmlbody')"
+. "$(realpath -- "${FILENAME%.*}.conf")"
+
+
+dates() {
+ if [ -z "$date_formatted" ]; then
+ return
+ fi
+
+ cat <<EOF
+ <section id="timestamps">
+ <p id="published-at">
+ Posted on <time datetime="$date_iso">$date_formatted</time>
+ </p>
+EOF
+
+ if [ -n "$updatedat_formatted" ]; then
+ cat <<EOF
+ <p id="updated-at">
+ Updated on <time datetime="$updatedat_iso">"$updatedat_formatted</time>"
+ </p>
+EOF
+ fi
+
+ cat <<EOF
+ </section>
+EOF
}
-extract_plaintext_snippets() (
- SNIPPETS="${FILENAME%.*}.snippets"
- printf '' > "$SNIPPETS"
- F="$(mkstemp)"
- cat > "$F"
- IFS=''
- BLOCK_NUMBER=0
- IN_BLOCK=
- while read -r line; do
- if [ "$line" = '</code></pre>' ]; then
- IN_BLOCK=
- fi
-
- if [ -n "$IN_BLOCK" ]; then
- printf '%s\n' "$line" | htmlesc -d >> "$OUT"
- fi
-
- if printf '%s' "$line" | grep -q "^$INDENT<pre><code"; then
- IN_BLOCK=1
- OUT="${FILENAME%.*}.html.$BLOCK_NUMBER.txt"
- BLOCK_NUMBER=$((BLOCK_NUMBER + 1))
- printf '%s\n' "$line" |
- sed "s|^\($INDENT<pre><code.*>\)\(.*\)$|\2|" |
- htmlesc -d > "$OUT"
- printf '%s\n' "$OUT" >> "$SNIPPETS"
- fi
- done < "$F"
-
- BLOCK_NUMBER=0
- while read -r line; do
- printf '%s\n' "$line"
-
- if [ "$line" = '</code></pre>' ]; then
- printf '%s<p class="plaintext-link"><a href="%s">plaintext</a></p>\n' \
- "$INDENT" \
- "$(basename "${url_part:?}").$BLOCK_NUMBER.txt"
- BLOCK_NUMBER=$((BLOCK_NUMBER + 1))
- fi
- done < "$F"
-)
-
-add_line_numbers() {
- awk '
- /^<\/code><\/pre>$/ {
- in_block = 0
- printf "</tbody></table>%s\n", $0
- next
- }
-
- match($0, /^( +<pre><code.*>)(.*)$/, a) {
- printf "%s<table rules=columns class=\"code-block\"><tbody>", a[1]
-
- n = 1
- block_count++
- printf "<tr><td class=\"line-number\"><a id=\"B%s-L%s\" href=\"#B%s-L%s\">%s</a></td><td class=\"code-line\">%s</td></tr>\n", block_count, n, block_count, n, n, a[2]
- in_block = 1
- next
- }
-
- in_block == 1 {
- n++
- printf "<tr><td class=\"line-number\"><a id=\"B%s-L%s\" href=\"#B%s-L%s\">%s</a></td><td class=\"code-line\">%s</td></tr>\n", block_count, n, block_count, n, n, $0
- next
- }
-
- { print }
- '
-}
+h1() {
+ if [ "${custom_body:-}" = true ]; then
+ return
+ fi
-add_headings_anchors() (
- IFS=''
- while read -r line; do
- if ! printf '%s' "$line" | grep -q "^$INDENT<h[2-6]>"; then
- printf '%s\n' "$line"
- continue
- fi
- LVL="$(printf '%s' "$line" | sed "s|^$INDENT<h\(.\)>.*|\1|")"
- HEADING="$(printf '%s' "$line" | sed "s|^$INDENT<h.>\(.*\)</h.>$|\1|")"
- SLUG="$(slugify "$HEADING")"
- printf '%s<h%s class="header-anchor" id="%s">%s<a href="#%s" aria-hidden="true"><img class="svg-icon" src="%s" /></a></h%s>\n' \
- "$INDENT" \
- "$LVL" \
- "$SLUG" \
- "$HEADING" \
- "$SLUG" \
- "${icon_link_url:?}" \
- "$LVL"
- done
-)
-
-
-warn_duplicate_ids() {
- F="$(mkstemp)"
- tee "$F"
- {
- grep "^$INDENT<h[2-6] class=\"header-anchor\" id=\"" |
- sed "s|^$INDENT<h[2-6] class=\"header-anchor\" id=\"\(.*\)\">.*<a href=.*$|\1|" |
- sort |
- uniq -c |
- awk -v F="$FILENAME" '$1 != 1 {
- printf "WARNING: duplicate header id: %s: %s\n", F, $2
- }'
- } >&2 < "$F"
- rm "$F"
+ cat <<EOF
+ <h1>
+ $title_html
+ </h1>
+EOF
}
-emit_body() {
- < "${FILENAME%.*}.content" \
- markdown_to_html |
- extract_plaintext_snippets |
- add_line_numbers |
- add_headings_anchors |
- warn_duplicate_ids
+comments() {
+ if [ "${custom_body:-}" = true ]; then
+ return
+ fi
+
+ cat <<EOF
+ <section>
+ <hr />
+ <footer>
+ <p id="comment">
+ <a href="$comment_url">Comment</a>
+ about this page and see
+ <a href="$discussions_url">existing discussions</a>
+ |
+ <a href="$sourcecode_url_prefix/$source_path">view source</a>
+ </p>
+ </footer>
+ </section>
+EOF
}
-if [ -r "$FILENAME".prev ]; then
- collection_head_prev_html="$(
- printf ' <link rel="prev" type="text/html" href="%s" />' \
- "$(url-for < "$FILENAME".prev)"
- )"
- export collection_head_prev_html
-fi
-if [ -r "$FILENAME".next ]; then
- collection_head_next_html="$(
- printf ' <link rel="next" type="text/html" href="%s" />' \
- "$(url-for < "$FILENAME".next)"
- )"
- export collection_head_next_html
+head_meta_author_html=
+if [ -n "${author:-}" ]; then
+ head_meta_author_html=" <meta name=\"author\" content=\"$author\" />"
fi
-envsubst < lib/preamble.html | sed '/^$/d'
-emit_body | tee "${FILENAME%.*}.htmlbody"
-envsubst < lib/postamble.html | sed '/^$/d'
+
+headlinks() {
+ if [ -z "${header_links:-}" ]; then
+ return
+ fi
+
+ echo ' <ol>'
+
+ while read -r line; do
+ link="$(printf '%s\n' "$line" | cut -d' ' -f1)"
+ name="$(printf '%s\n' "$line" | cut -d' ' -f2)"
+ cat <<EOF
+ <li>
+ <a href="$base_url_prefix/$link">$name</a>
+ </li>
+EOF
+ done < "$header_links"
+
+ echo ' </ol>'
+}
+
+
+collection_head_prev_html=
+collection_head_post_html=
+cat <<EOF | sed '/^$/d'
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="UTF-8" />
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
+$head_meta_author_html
+ <link rel="stylesheet" type="text/css" href="$css_url" />
+ <link rel="shortcut icon" type="image/svg+xml" href="$favicon_url" />
+ <link rel="canonical" type="text/html" href="$url_absolute" />
+ <link rel="alternate" type="application/atom+xml" href="$atom_url" title="$feed_title_html" />
+$collection_head_prev_html
+$collection_head_post_html
+ <title>$titlefull_html</title>
+ </head>
+ <body>
+ <header>
+ <nav>
+ <a href="$base_url_prefix/">
+ <picture>
+ <source srcset="$logo_url_prefix/dark.svg" media="(prefers-color-scheme: dark)" />
+ <img src="$logo_url_prefix/light.svg" alt="$logo_alt" />
+ </picture>
+ </a>
+$(headlinks)
+ </nav>
+ <hr />
+ </header>
+ <main>
+ <article>
+EOF
+
+h1
+dates
+
+cat "$FILENAME"
+
+comments
+
+cat <<EOF
+ </article>
+ </main>
+ <footer>
+ <hr />
+ <ul>
+ <li>
+ <picture>
+ <source srcset="$envelopeicon_url_prefix/dark.svg" media="(prefers-color-scheme: dark)" />
+ <img src="$envelopeicon_url_prefix/light.svg" class="icon" alt="An outlined icon of an envelope" />
+ </picture>
+ <a href="mailto:$email">$email</a>
+ </li>
+ </ul>
+ <p id="license">
+ The content for this site is licensed under
+ <a rel="license" href="https://creativecommons.org/licenses/by-sa/4.0/">CC BY-SA 4.0</a>.
+ The <a href="$sourcecode_url/">code</a> is
+ <a rel="license" href="$sourcecode_url_prefix/COPYING">AGPLv3 or later</a>.
+ Patches welcome.
+ </p>
+ </footer>
+ </body>
+</html>
+EOF
diff --git a/src/htmlbody b/src/htmlbody
index 53a4485..e4e5692 100755
--- a/src/htmlbody
+++ b/src/htmlbody
@@ -1,4 +1,26 @@
#!/bin/sh
-set -eu
+set -euo pipefail
-cat "${1:--}" | asciidoctor -s -
+
+usage() {
+ echo 'Usage: htmlbody FILENAME.adoc'
+}
+
+FILENAME="${1:-}"
+eval "$(assert-arg -- "$FILENAME" 'FILENAME.adoc')"
+
+
+plaintext_links() {
+ awk -v BASE="$(basename "$FILENAME" .adoc)".html l'
+ { print }
+ /^----$/ {
+ in_block = !in_block
+ if (in_block) {
+ next
+ }
+ file = BASE "." count++ ".txt"
+ print "link:" file "[plaintext,role=plaintext]"
+ }' "$1"
+}
+
+plaintext_links "$FILENAME" | asciidoctor -s -
diff --git a/src/indexbody b/src/indexbody
new file mode 100755
index 0000000..93b4f90
--- /dev/null
+++ b/src/indexbody
@@ -0,0 +1,24 @@
+#!/bin/sh
+set -euo pipefail
+
+
+usage() {
+ echo 'Usage: index FILENAME.conf FILENAME.sortdata...]'
+}
+
+FILENAME="${1:-}"
+FILES="${2:-}"
+eval "$(assert-arg -- "$FILENAME" 'FILENAME.conf')"
+eval "$(assert-arg -- "$FILES" 'FILENAME.sortdata...')"
+. "$(realpath -- "$FILENAME")"
+shift
+
+
+printf ' <ol class="collection-list">\n'
+find "$@" |
+ xargs cat |
+ sort -nr |
+ xargs cat |
+ sed 's/\.conf$/.indexentry/' |
+ xargs cat
+printf ' </ol>\n'
diff --git a/src/indexentry b/src/indexentry
new file mode 100755
index 0000000..07ffa4a
--- /dev/null
+++ b/src/indexentry
@@ -0,0 +1,20 @@
+#!/bin/sh
+set -euo pipefail
+
+
+usage() {
+ echo 'Usage: indexentry FILENAME.conf'
+}
+
+FILENAME="${1:-}"
+eval "$(assert-arg -- "$FILENAME" 'FILENAME.conf')"
+. "$(realpath -- "$FILENAME")"
+
+
+cat <<EOF
+ <li>
+ $date_formatted
+ <br />
+ <a href="$url">$title_html</a>
+ </li>
+EOF
diff --git a/src/mkwb.in b/src/mkwb.in
index 2c698e1..438f779 100755
--- a/src/mkwb.in
+++ b/src/mkwb.in
@@ -1,5 +1,6 @@
#!/bin/sh
-set -eu
+set -euo pipefail
+
usage() {
echo 'Usage: mkwb ACTION [OPTION...]'
@@ -9,4 +10,5 @@ ACTION="${1:-}"
eval "$(assert-arg -- "$ACTION" 'ACTION')"
shift
+
exec '@LIBEXECDIR@'/"$ACTION" "$@"
diff --git a/src/snippets b/src/snippets
new file mode 100755
index 0000000..e2d7557
--- /dev/null
+++ b/src/snippets
@@ -0,0 +1,27 @@
+#!/bin/sh
+set -euo pipefail
+
+
+usage() {
+ echo 'Usage: snippets FILENAME.adoc'
+}
+
+FILENAME="${1:-}"
+eval "$(assert-arg -- "$FILENAME" 'FILENAME.adoc')"
+
+
+awk -v BASE="${FILENAME%.adoc}.html" '
+/^----$/ {
+ if (!in_block) {
+ file = BASE "." count++ ".txt"
+ system("rm -f " file)
+ }
+ in_block = !in_block
+ next
+}
+
+in_block {
+ print >> file
+ print file
+}
+' "$FILENAME"
diff --git a/src/sortdata b/src/sortdata
index 5b0b238..df64e9f 100755
--- a/src/sortdata
+++ b/src/sortdata
@@ -1,14 +1,16 @@
#!/bin/sh
-set -eu
+set -euo pipefail
+
usage() {
- echo 'Usage: sortdata ENTRYPATH'
+ echo 'Usage: sortdata FILENAME.conf'
}
-ENTRYPATH="${1:-}"
-eval "$(assert-arg -- "$ENTRYPATH" 'ENTRYPATH')"
-. "${ENTRYPATH%.*}.conf"
+FILENAME="${1:-}"
+eval "$(assert-arg -- "$FILENAME" 'FILENAME.conf')"
+. "$(realpath -- "$FILENAME")"
+
-f=src/"$date_iso".sortdata
-ln -frs "${ENTRYPATH%.*}.xmlentry" "$f" # FIXME: -r is no POSIX
+f=src/"$date_iso"-"${sort:-0}".sortdata
+printf '%s\n' "$FILENAME" > "$f"
printf '%s\n' "$f"