diff options
Diffstat (limited to '')
-rw-r--r-- | v2/src/content/pastebins/sicp-exercise-3-19.md | 113 | ||||
l--------- | v2/src/content/security.txt | 1 | ||||
l--------- | v2/src/content/static/atom.svg | 1 | ||||
l--------- | v2/src/content/static/envelope.svg | 1 | ||||
l--------- | v2/src/content/static/favicon.svg | 1 | ||||
l--------- | v2/src/content/static/link.svg | 1 | ||||
l--------- | v2/src/content/static/lock.svg | 1 | ||||
l--------- | v2/src/content/static/public.asc.txt | 1 | ||||
-rw-r--r-- | v2/src/content/static/styles.css | 149 | ||||
-rw-r--r-- | v2/src/development/config.env.in | 5 | ||||
-rwxr-xr-x | v2/src/development/dynmake.sh | 75 | ||||
-rwxr-xr-x | v2/src/development/genhtml.sh | 332 |
12 files changed, 681 insertions, 0 deletions
diff --git a/v2/src/content/pastebins/sicp-exercise-3-19.md b/v2/src/content/pastebins/sicp-exercise-3-19.md new file mode 100644 index 0000000..fd2c52b --- /dev/null +++ b/v2/src/content/pastebins/sicp-exercise-3-19.md @@ -0,0 +1,113 @@ +--- + +TITLE='SICP exercise 3.19' + +DATE='2021-09-02' + +LAYOUT='post' + +LANGUAGE='en' + +REF='sicp-exercise-3-19' + +--- + +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/security.txt b/v2/src/content/security.txt new file mode 120000 index 0000000..abdf74b --- /dev/null +++ b/v2/src/content/security.txt @@ -0,0 +1 @@ +.well-known/security.txt
\ No newline at end of file diff --git a/v2/src/content/static/atom.svg b/v2/src/content/static/atom.svg new file mode 120000 index 0000000..41c6d3f --- /dev/null +++ b/v2/src/content/static/atom.svg @@ -0,0 +1 @@ +../../../../static/atom.svg
\ No newline at end of file diff --git a/v2/src/content/static/envelope.svg b/v2/src/content/static/envelope.svg new file mode 120000 index 0000000..bd0c577 --- /dev/null +++ b/v2/src/content/static/envelope.svg @@ -0,0 +1 @@ +../../../../static/envelope.svg
\ No newline at end of file diff --git a/v2/src/content/static/favicon.svg b/v2/src/content/static/favicon.svg new file mode 120000 index 0000000..33566ab --- /dev/null +++ b/v2/src/content/static/favicon.svg @@ -0,0 +1 @@ +../../../../static/lord-favicon.svg
\ No newline at end of file diff --git a/v2/src/content/static/link.svg b/v2/src/content/static/link.svg new file mode 120000 index 0000000..bf69c40 --- /dev/null +++ b/v2/src/content/static/link.svg @@ -0,0 +1 @@ +../../../../static/link.svg
\ No newline at end of file diff --git a/v2/src/content/static/lock.svg b/v2/src/content/static/lock.svg new file mode 120000 index 0000000..f9a4f33 --- /dev/null +++ b/v2/src/content/static/lock.svg @@ -0,0 +1 @@ +../../../../static/lock.svg
\ No newline at end of file diff --git a/v2/src/content/static/public.asc.txt b/v2/src/content/static/public.asc.txt new file mode 120000 index 0000000..5175f38 --- /dev/null +++ b/v2/src/content/static/public.asc.txt @@ -0,0 +1 @@ +../../../../public.asc
\ No newline at end of file diff --git a/v2/src/content/static/styles.css b/v2/src/content/static/styles.css new file mode 100644 index 0000000..0ec67a8 --- /dev/null +++ b/v2/src/content/static/styles.css @@ -0,0 +1,149 @@ +/* General declarations */ + +body { + margin: 0px auto; + padding: 1%; + max-width: 750px; +} + +.svg-icon { + vertical-align: middle; +} + + +/* Navigation header */ + +nav a { + color: maroon; + font-size: 18px; + margin: 12px; + text-decoration: none; +} + +nav ul, nav li { + display: inline; +} + +nav ul li a { + color: black; + font-size: 14px; + margin: 6px; +} + + +/* Article bodies */ + +.timestamp { + color: #555; + font-size: 14px; + font-style: italic; +} + +blockquote { + font-style: italic; + color: dimgrey; + padding-left: 10px; + border-left: 3px solid #ccc; +} + +ul.no-style { + list-style-type: none; +} + +ul.no-style li { + margin: 20px 0px; +} + + +/* Footer */ + +footer { + font-size: 14px; + margin-top: 30px; + padding: 12px 0px 12px 0px; +} + +footer li { + list-style-type: none; + margin-top: 10px; +} + +footer li a { + margin-left: 5px; + user-select: none; +} + +/* Code blocks */ + +/* The "lineno" class is the default generated by Rouge for table-row in code blocks, see: + https://github.com/rouge-ruby/rouge */ +.line-number, pre.lineno { + margin-right: 3px; + padding-right: 3px; + border-right: 1px solid; + border-color: hsla(0, 0%, 0%, 0.3); + text-align: right; + user-select: none; +} + +.code-line { + padding-left: 8px; +} + +.code-block { + padding: 6px 4px; + display: block; +} + +.code-block, pre.highlight { + border: 1px solid #ccc; + border-radius: 10px; +} + +pre { + overflow: auto; +} + + +/* Code block anchors */ + +.line-number a, a.code-line-anchor { + color: black; + text-decoration: none; +} + +a.code-line-anchor:hover { + text-decoration: underline; +} + + +/* Header anchor */ + +.header-anchor { + color: black; + text-decoration: none; + display: block; + margin-bottom: 15px; +} + +.header-anchor { +} + + +.header-anchor img { + margin-left: 5px; + visibility: hidden; +} + +.header-anchor:hover img { + visibility: visible; +} + + +/* Plaintext code block links */ + +.plaintext-link { + margin: auto auto 0 auto; + text-align: right; + font-family: monospace; +} diff --git a/v2/src/development/config.env.in b/v2/src/development/config.env.in new file mode 100644 index 0000000..18d5367 --- /dev/null +++ b/v2/src/development/config.env.in @@ -0,0 +1,5 @@ +#!/bin/sh + +FQDN='@FQDN@' +BASE_URL='@BASE_URL@' +DATE_FMT='+%B %-d, %Y' diff --git a/v2/src/development/dynmake.sh b/v2/src/development/dynmake.sh new file mode 100755 index 0000000..a04e70e --- /dev/null +++ b/v2/src/development/dynmake.sh @@ -0,0 +1,75 @@ +#!/bin/sh +set -eu + + +usage() { + cat <<-'EOF' + Usage: + dynmake.sh + dynmake.sh -h + EOF +} + +help() { + cat <<-'EOF' + + Options: + -h, --help show this message + + + Generate make(1) code for later evaluation by make(1). What + this scripts does is fill the gap where make(1) can't handle + globs and dynamic dependencies, and uses some ad-hoc scripts + to generate those. + 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)) + + + +varlist() { + sed -e 's/^/ /' \ + -e 's/$/ \\/' +} + + +# +# Pastebins +# + +pastebins() { + find src/content/pastebins/ -name '*.md' +} + +printf 'pastebins.md = \\\n' +pastebins | varlist +printf '\n' diff --git a/v2/src/development/genhtml.sh b/v2/src/development/genhtml.sh new file mode 100755 index 0000000..953a80d --- /dev/null +++ b/v2/src/development/genhtml.sh @@ -0,0 +1,332 @@ +#!/bin/sh +set -eu + +# FIXMEs: +# - feeds +# - link to next and/or previous in <head> +# - translation support +# - validate input variables: regex for date (same as _plugins/linter.rb) +# - `date -d` isn't POSIX +# - parse commonmark and use a custom HTML emitter over <pre><code> regex +# - handle mixture of personal scripts +# - sitemap? How does it even work? +# - dark mode +# - generate security.txt dynamically +# - make url_for a standalone executable +# - config.env should depend on dynamic.mk? + + + +usage() { + cat <<-'EOF' + Usage: + genhtml.sh FILENAME + genhtml.sh -h + EOF +} + +help() { + cat <<-'EOF' + + Options: + -h, --help show this message + + FILENAME the name of the input file, to also be used as + URL + + + 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 + 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)) + + +FILENAME="${1:-}" +eval "$(assert-arg "$FILENAME" 'FILENAME')" + + +# +# Utility functions +# + +url_for() { + printf '%s/%s' "$BASE_URL" "$1" +} + +absolute() { + printf 'https://%s%s' "$FQDN" "$(cat)" +} + +translate() { + printf '%s' "$1" +} + +_() { + translate "$1" | html +} + +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 +} + +extract_content() { + awk ' + separator >= 2 + /^---$/ { separator++ } + ' +} + +add_preamble() { + printf '%s\n%s\n' "$PREAMBLE" "$(cat -)" +} + +markdown_to_html() { + md2html +} + +extract_plaintext_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" | html -d >> "$OUT" + fi + + if printf '%s' "$line" | grep -q '^<pre><code.*>'; then + IN_BLOCK=1 + OUT="${FILENAME%.md}.html.$BLOCK_NUMBER.txt" + BLOCK_NUMBER=$((BLOCK_NUMBER + 1)) + printf '%s\n' "$line" | + sed 's|^\(<pre><code.*>\)\(.*\)$|\2|' | + html -d > "$OUT" + fi + done < "$F" + + BLOCK_NUMBER=0 + while read -r line; do + printf '%s\n' "$line" + + if [ "$line" = '</code></pre>' ]; then + printf '<p class="plaintext-link"><a href="%s.%s.txt">plaintext</a></p>\n' "$(url_for "$URL")" "$BLOCK_NUMBER" + 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 '^<h[2-6]>'; then + printf '%s\n' "$line" + continue + fi + LVL="$(printf '%s' "$line" | sed 's|^<h\(.\)>.*|\1|')" + HEADING="$(printf '%s' "$line" | sed 's|^<h.>\(.*\)</h.>$|\1|')" + SLUG="$(slugify_once "$HEADING")" + printf '<h%s class="header-anchor" id="%s">%s<a href="#%s" aria-hidden="true"><img class="svg-icon" src="%s" /></a></h%s>\n' \ + "$LVL" \ + "$SLUG" \ + "$HEADING" \ + "$SLUG" \ + "$(url_for 'static/link.svg')" \ + "$LVL" + done + ) +} + +emit_body() { + cat "$FILENAME" | + extract_content | + add_preamble | + markdown_to_html | + extract_plaintext_snippets | + add_line_numbers | + add_headings_anchors +} + + +# +# Environment variables +# + +. src/development/config.env + +eval "$( + awk ' + /^---$/ { if (++separator > 1) exit; else next; } + { print } + ' "$FILENAME" +)" + +SITE_NAME="$(_ "EuAndreh's website")" +TITLE="$(_ "${TITLE:-$SITE_NAME}")" +URI_TITLE="$(printf '%s' "$TITLE" | uri)" +URL="$(printf '%s' "$FILENAME" | sed -e 's|^src/content/||' -e 's|md$|html|')" + +PREAMBLE="$( + cat <<-EOF + # $TITLE + + <p class="timestamp"> + Posted on <time datetime="$DATE">$(LANG="$LANGUAGE" date -d "$DATE" "$DATE_FMT")</time> + </p> + EOF +)" + + + +# +# Main: generate the HTML to STDOUT. +# + +cat <<-EOF + <!DOCTYPE html> + <html lang="$LANGUAGE"> + <head> + <meta charset="UTF-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1" /> + <link rel="stylesheet" type="text/css" href="$(url_for 'static/styles.css')" /> + <link rel="icon" type="image/svg+xml" href="$(url_for 'static/favicon.svg')" /> + + <title>$TITLE</title> + + <meta name="author" content="EuAndreh" /> + <meta property="og:site_name" content="$SITE_NAME" /> + <meta property="og:locale" content="$LANGUAGE" /> + <meta property="og:title" content="$TITLE" /> + + <link rel="canonical" href="$(url_for "$URL" | absolute)" /> + <meta property="og:url" content="$(url_for "$URL" | absolute)" /> + </head> + <body> + <header> + <nav> + <ul> + <a href="$(url_for "$LANGUAGE/")">$(_ 'EuAndreh')</a> + <a href="$(url_for "$(_ 'about.html')")">$(_ 'About')</a> + </ul> + </nav> + <hr /> + </header> + <main> + <article> + $(emit_body) + <hr /> + <p class="post-footer"> + <a href="mailto:~euandreh/public-inbox@lists.sr.ht?Subject=Re%3A%20$URI_TITLE">Comment</a> + and see + <a href="https://lists.sr.ht/~euandreh/public-inbox?search=$URI_TITLE">existing discussions</a> + | + <a href="https://euandreh.xyz/euandre.org.git/tree/$FILENAME">view source</a> + </p> + </article> + </main> + <footer> + <hr /> + <ul> + <li> + <img class="svg-icon" src="$(url_for 'static/envelope.svg')" alt="$(_ 'a envelope icon representing an email address')" /> + <a href="mailto:eu@euandre.org">eu@euandre.org</a> + </li> + <li> + <img class="svg-icon" src="$(url_for 'static/lock.svg')" alt="$(_ 'a lock icon representing a GPG public key')" /> + <a href="$(url_for 'static/public.asc.txt')">81F90EC3CD356060</a> + </li> + </ul> + <p> + $(translate '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="https://euandreh.xyz/euandre.org.git">code</a> is <a rel="license" href="https://euandreh.xyz/euandre.org.git/tree/COPYING">AGPLv3 or later</a>. Patches welcome.') + </p> + </footer> + </body> + </html> +EOF |