diff options
Diffstat (limited to 'v2/src/bin')
-rwxr-xr-x | v2/src/bin/absolute | 2 | ||||
-rwxr-xr-x | v2/src/bin/collections | 69 | ||||
-rwxr-xr-x | v2/src/bin/conf | 166 | ||||
-rwxr-xr-x | v2/src/bin/feed | 91 | ||||
-rwxr-xr-x | v2/src/bin/html | 219 | ||||
-rwxr-xr-x | v2/src/bin/lang-for | 73 | ||||
-rwxr-xr-x | v2/src/bin/langs | 69 | ||||
-rwxr-xr-x | v2/src/bin/makemake | 142 | ||||
-rwxr-xr-x | v2/src/bin/security-txt | 82 | ||||
-rwxr-xr-x | v2/src/bin/url-for | 30 | ||||
-rwxr-xr-x | v2/src/bin/xmlentry | 81 |
11 files changed, 946 insertions, 78 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/bin/conf b/v2/src/bin/conf new file mode 100755 index 0000000..ac02d98 --- /dev/null +++ b/v2/src/bin/conf @@ -0,0 +1,166 @@ +#!/bin/sh +set -eu + + +usage() { + cat <<-'EOF' + Usage: + conf FILENAME + conf -h + EOF +} + +help() { + cat <<-'EOF' + + Options: + -h, --help show this message + + FILENAME the name of the input file, also to be used as + URL. + + + Separate the content from the "frontmatter", and emit the + selected one, given the FILENAME. + + + Examples: + + Get the "frontmatter" of src/f.conf: + + $ conf src/f.md > src/f.conf + 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')" + + +escape() { + sed 's|\([`"$]\)|\\\1|g' +} + +tee "$FILENAME".tmp < src/lib/base.conf +DELIMITER=0 +while read -r line; do + if [ "$line" = '---' ]; then + DELIMITER=$((DELIMITER + 1)) + continue + fi + if [ "$DELIMITER" = 2 ]; then + break + fi + if [ -z "$line" ]; then + continue + fi + + KEY="$( printf '%s' "$line" | cut -d: -f1)" + VALUE="$(printf '%s' "$line" | cut -d: -f2- | sed 's|^ ||' | escape)" + printf 'export %s="%s"\n' "$KEY" "$VALUE" +done < "$FILENAME" | tee -a "$FILENAME".tmp +# shellcheck source=/dev/null +. "$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 +if [ -z "${title:-}" ]; then + title="${site_name:?}" + printf 'export title="%s"\n' "$(printf '%s' "$title" | escape)" +fi + +if [ -n "${date:-}" ]; then + 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 + 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|^$CONTENT_PREFIX||")" +title_uri="$(uri "$title")" + +printf 'export title_html="%s"\n' "$(printf '%s' "$title" | htmlesc | escape)" +printf 'export filename="%s"\n' "$FILENAME" +printf 'export url_part="%s"\n' "$url_part" +printf 'export url="%s"\n' "$(url-for "$url_part" | absolute)" +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 '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 "$CONTENT_PREFIX"/img/*.svg; do + name="$(basename "$f" .svg | sed 's|-|_|g')" + printf 'export icon_%s_url="%s"\n' "$name" "$(url-for "img/$(basename "$f")")" +done + +# FIXME: special treatment of root +printf 'export homepage_url="%s"\n' "$(url-for '/')" + +printf 'export about_url="%s"\n' "$(url-for "${about_url_name:?}")" + + +if [ "${layout:-}" = 'post' ]; then + export mailto_uri="$mailto_uri_prefix$title_uri" + export discussions_url="$discussions_url_prefix$title_uri" + export sourcecode_url="$sourcecode_url_prefix$FILENAME" + printf 'export comment_html="%s"\n' "$(envsubst < src/lib/comment."$lang".html | escape)" +fi 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/bin/html b/v2/src/bin/html new file mode 100755 index 0000000..7e6809c --- /dev/null +++ b/v2/src/bin/html @@ -0,0 +1,219 @@ +#!/bin/sh +set -eu + +usage() { + cat <<-'EOF' + Usage: + html FILENAME + html -h + EOF +} + +help() { + cat <<-'EOF' + + + Options: + -h, --help show this message + + FILENAME the name of the input file .md file + + + Process the FILENAME, and generate a full HTML page. + + + Examples: + + Generate the HTML for a pastebin: + + $ html src/a-paste.md > src/a-paste.html + EOF +} + + +for f in "$@"; do + case "$f" 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" + +# +# Utility functions +# + +SEEN_SLUGS="$(mkstemp)" +slugify_once() { + SLUG="$(printf '%s' "$1" | slugify)${2:+-$2}" + if grep -q "^$SLUG$" "$SEEN_SLUGS"; then + N="${2:-0}" + N=$((N + 1)) + slugify_once "$1" "$N" + else + printf '%s\n' "$SLUG" >> "$SEEN_SLUGS" + printf '%s' "$SLUG" + fi +} + +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 + } + ' +} + +extract_plaintext_snippets() { + SNIPPETS="${FILENAME%.md}.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%.md}.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 } + ' +} + +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_once "$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 + ) +} + +emit_body() { + < "${FILENAME%.md}.content" \ + markdown_to_html | + extract_plaintext_snippets | + add_line_numbers | + add_headings_anchors +} + +envsubst < src/lib/preamble.html +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/bin/security-txt b/v2/src/bin/security-txt new file mode 100755 index 0000000..7026969 --- /dev/null +++ b/v2/src/bin/security-txt @@ -0,0 +1,82 @@ +#!/bin/sh +set -eu + +usage() { + cat <<-'EOF' + Usage: + security-txt + security-txt -h + EOF +} + +help() { + cat <<-'EOF' + + + Options: + -h, --help show this message + + + Generate the RFC 9116 "security.txt" file from data in the + repository. + + + Examples: + + Just run it: + + $ security-txt > .well-known/security.txt + 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)) + + + +EXPIRES="$( + LANG=C.UTF-8 gpg --list-key "$EMAIL" | + awk '/^pub/ { print substr($(NF), 1, 10) }' +)T00:00:00z" + +LANGUAGES="$( + langs | + sed 's|^|, |' | + tr -d '\n' | + sed 's|^, ||' +)" + + +cat <<-EOF + Contact: mailto:$EMAIL + Encryption: $(url-for 'public.asc.txt' | absolute) + Expires: $EXPIRES + 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' |