aboutsummaryrefslogtreecommitdiff
path: root/share/aux-repo/aux
diff options
context:
space:
mode:
Diffstat (limited to 'share/aux-repo/aux')
-rw-r--r--share/aux-repo/aux/.gitignore1
-rwxr-xr-xshare/aux-repo/aux/ci/ci-build.sh66
-rwxr-xr-xshare/aux-repo/aux/ci/git-post-receive.sh22
-rwxr-xr-xshare/aux-repo/aux/ci/git-pre-push.sh22
-rwxr-xr-xshare/aux-repo/aux/ci/report.sh158
-rw-r--r--share/aux-repo/aux/lib.sh33
-rw-r--r--share/aux-repo/aux/tld.txt1
-rwxr-xr-xshare/aux-repo/aux/workflow/TODOs.sh65
-rw-r--r--share/aux-repo/aux/workflow/favicon.svg62
-rw-r--r--share/aux-repo/aux/workflow/head.html2
-rwxr-xr-xshare/aux-repo/aux/workflow/md2html.sh87
-rw-r--r--share/aux-repo/aux/workflow/preamble.md.in16
-rw-r--r--share/aux-repo/aux/workflow/style.css80
13 files changed, 615 insertions, 0 deletions
diff --git a/share/aux-repo/aux/.gitignore b/share/aux-repo/aux/.gitignore
new file mode 100644
index 0000000..93cad91
--- /dev/null
+++ b/share/aux-repo/aux/.gitignore
@@ -0,0 +1 @@
+/workflow/preamble.md
diff --git a/share/aux-repo/aux/ci/ci-build.sh b/share/aux-repo/aux/ci/ci-build.sh
new file mode 100755
index 0000000..8d49779
--- /dev/null
+++ b/share/aux-repo/aux/ci/ci-build.sh
@@ -0,0 +1,66 @@
+#!/bin/sh
+set -eux
+
+PROJECT="$1"
+LOGS_DIR="$2"
+SHA="$3"
+FILENAME="$(date -Is)-$SHA.log"
+LOGFILE="$LOGS_DIR/$FILENAME"
+
+mkdtemp() {
+ name="$(echo 'mkstemp(template)' |
+ m4 -D template="${TMPDIR:-/tmp}/m4-tmpname.")"
+ rm -f "$name"
+ mkdir "$name"
+ echo "$name"
+}
+
+{
+ echo "Starting CI job at: $(date -Is)"
+
+ finish() {
+ STATUS="$?"
+ printf "\n\n>>> exit status was %s\n" "$STATUS"
+ echo "Finishing CI job at: $(date -Is)"
+ cd -
+ NOTE=$(cat <<EOF
+See CI logs with:
+ git notes --ref=refs/notes/ci-logs show $SHA
+ git notes --ref=refs/notes/ci-data show $SHA
+EOF
+)
+ git notes --ref=refs/notes/ci-data add -f -m "$STATUS $FILENAME"
+ git notes --ref=refs/notes/ci-logs add -f -F "$LOGFILE"
+ git notes append -m "$NOTE"
+
+ cd -
+ git fetch origin refs/notes/*:refs/notes/*
+ sh aux/ci/report.sh -n "$PROJECT" -o public
+ rsync -av public/ "/opt/www/$TLD/static/$PROJECT/"
+
+ tar \
+ -C "/opt/www/$TLD/git/repos" \
+ -c \
+ -f "/opt/www/$TLD/static/$PROJECT/repo.tar.gz" \
+ "$PROJECT".git
+
+ printf '\n>>>\n>>> CI logs added as Git note.\n>>>\n>>> Run status was %s\n>>>\n\n' \
+ "$STATUS"
+ }
+ trap finish EXIT
+
+ unset GIT_DIR
+ REMOTE="$PWD"
+ cd "$(mkdtemp)"
+ git clone "$REMOTE" .
+ git config --global user.email git@euandre.org
+ git config --global user.name 'EuAndreh CI'
+
+ if [ -e aux/with-container ]; then
+ RUNNER='sh aux/with-container'
+ else
+ RUNNER='sh -c'
+ fi
+
+ $RUNNER 'make clean dev-check'
+} 2>&1 | tee "$LOGFILE"
diff --git a/share/aux-repo/aux/ci/git-post-receive.sh b/share/aux-repo/aux/ci/git-post-receive.sh
new file mode 100755
index 0000000..f813259
--- /dev/null
+++ b/share/aux-repo/aux/ci/git-post-receive.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+set -eu
+
+for n in $(seq 0 $((GIT_PUSH_OPTION_COUNT - 1))); do
+ opt="$(eval "echo \$GIT_PUSH_OPTION_$n")"
+ if [ "$opt" = skip-ci ] || [ "$opt" = ci-skip ]; then
+ printf "\n'%s' option detected, not running ci-build.sh\n\n" \
+ "$opt"
+ exit 0
+ fi
+done
+
+# shellcheck disable=2034
+read -r _oldrev SHA _refname
+
+PROJECT="$(basename "$PWD" | cut -d. -f1)" # remove .git suffix
+LOGS_DIR="/opt/ci/$PROJECT/logs"
+sh "/opt/ci/$PROJECT/ci-build.sh" "$PROJECT" "$LOGS_DIR" "$SHA" ||:
+
+echo 'To retrigger the build, run:'
+echo "cd /opt/www/$TLD/git/repos/$PROJECT.git/"
+echo "sh /opt/www/$TLD/git/ci/$PROJECT/ci-build.sh" "$PROJECT" "$LOGS_DIR" "$SHA"
diff --git a/share/aux-repo/aux/ci/git-pre-push.sh b/share/aux-repo/aux/ci/git-pre-push.sh
new file mode 100755
index 0000000..9883769
--- /dev/null
+++ b/share/aux-repo/aux/ci/git-pre-push.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+set -eux
+
+TLD="$(cat aux/tld.txt)"
+. aux/lib.sh
+
+PROJECT="$(basename "$PWD")"
+LOGS_DIR="/opt/www/$TLD/git/ci/$PROJECT/logs"
+REMOTE_GIT_DIR="/opt/www/$TLD/git/repos/$PROJECT.git"
+
+DESCRIPTION="$(mkstemp)"
+if [ -f description ]
+then
+ cp description "$DESCRIPTION"
+else
+ git config euandreh.description > "$DESCRIPTION"
+fi
+
+scp "$DESCRIPTION" "$TLD:$REMOTE_GIT_DIR/description"
+ssh "$TLD" mkdir -p "$LOGS_DIR"
+scp aux/ci/ci-build.sh "$TLD:$(dirname "$LOGS_DIR")/ci-build.sh"
+scp aux/ci/git-post-receive.sh "$TLD:$REMOTE_GIT_DIR/hooks/post-receive"
diff --git a/share/aux-repo/aux/ci/report.sh b/share/aux-repo/aux/ci/report.sh
new file mode 100755
index 0000000..21cc54e
--- /dev/null
+++ b/share/aux-repo/aux/ci/report.sh
@@ -0,0 +1,158 @@
+#!/bin/sh
+set -eu
+
+TLD="$(cat aux/tld.txt)"
+. aux/lib.sh
+
+
+usage() {
+ cat <<-'EOF'
+ Usage:
+ aux/ci/report.sh -n NAME -o OUTDIR
+ aux/ci/report.sh -h
+ EOF
+}
+
+help() {
+ cat <<-'EOF'
+
+
+ Options:
+ -n NAME the lowercase name of the project
+ -o OUTDIR directory where to write the files
+ -h, --help show this message
+
+
+ Generate static HTML files CI report from data stored in git
+ notes. The metadata about the CI runs are stored in the ref
+ "refs/notes/ci-data", in the format described by
+ "aux/ci/run.sh", and the raw logs are stored under the ref
+ "refs/notes/ci-logs".
+
+
+ Examples:
+
+ Generate report for project "myapp" in "public/ci/":
+
+ $ sh aux/ci/report.sh -n myapp -o public/ci
+ EOF
+}
+
+
+for flag in "$@"; do
+ case "$flag" in
+ --)
+ break
+ ;;
+ --help)
+ usage
+ help
+ exit
+ ;;
+ *)
+ ;;
+ esac
+done
+
+while getopts 'n:o:h' flag; do
+ case "$flag" in
+ n)
+ NAME="$OPTARG"
+ ;;
+ o)
+ OUTDIR="$OPTARG"
+ ;;
+ h)
+ usage
+ help
+ exit
+ ;;
+ *)
+ usage >&2
+ exit 2
+ ;;
+ esac
+done
+shift $((OPTIND - 1))
+
+
+eval "$(assert_arg "${NAME:-}" '-n NAME')"
+eval "$(assert_arg "${OUTDIR:-}" '-o OUTDIR')"
+
+PASS='✅'
+FAIL='❌'
+
+mkdir -p "$OUTDIR"/logs "$OUTDIR"/data
+
+for c in $(git notes list | cut -d' ' -f2); do
+ DATA="$(git notes --ref=refs/notes/ci-data show "$c")"
+ FILENAME="$(echo "$DATA" | cut -d' ' -f2)"
+ echo "$DATA" > "$OUTDIR/data/$FILENAME"
+ git notes --ref=refs/notes/ci-logs show "$c" \
+ > "$OUTDIR/logs/$FILENAME"
+done
+
+{
+ cat <<-EOF
+ <!DOCTYPE html>
+ <html lang="en">
+ <head>
+ <meta charset="UTF-8" />
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
+ <meta name="description" content="CI logs for $NAME" />
+ <link rel="icon" type="image/svg+xml" href="favicon.svg" />
+ <title>$NAME - CI logs</title>
+
+ <style>
+ EOF
+
+ cat aux/workflow/style.css | sed 's|^| |'
+
+ cat <<-EOF
+ </style>
+
+ <style>
+ pre {
+ display: inline;
+ }
+ ol {
+ list-style-type: disc;
+ }
+ </style>
+ </head>
+ <body>
+ <main>
+ <h1>
+ CI logs for
+ <a href="https://$TLD/$NAME/en/">$NAME</a>
+ </h1>
+ <ol>
+ EOF
+
+ for f in $(find "$OUTDIR/data/" -type f | LANG=C.UTF-8 sort -r); do
+ DATA="$(cat "$f")"
+ STATUS="$(echo "$DATA" | cut -d\ -f1)"
+ FILENAME="$(echo "$DATA" | cut -d\ -f2)"
+
+ if [ "$STATUS" = 0 ]; then
+ STATUS_MARKER="$PASS"
+ else
+ STATUS_MARKER="$FAIL"
+ fi
+
+ cat <<-EOF
+ <li>
+ <a href="logs/$FILENAME">$STATUS_MARKER <pre>$FILENAME</pre></a>
+ </li>
+ EOF
+ done
+
+ cat <<-EOF
+ </ol>
+ </main>
+ </body>
+ </html>
+ EOF
+} > "$OUTDIR"/index.html.tmp
+
+mv "$OUTDIR"/index.html.tmp "$OUTDIR"/index.html
diff --git a/share/aux-repo/aux/lib.sh b/share/aux-repo/aux/lib.sh
new file mode 100644
index 0000000..9d183f9
--- /dev/null
+++ b/share/aux-repo/aux/lib.sh
@@ -0,0 +1,33 @@
+#!/bin/sh
+
+assert_arg() {
+ if [ -z "$1" ]; then
+ printf 'Missing %s.\n\n' "$2" >&2
+ cat <<-'EOF'
+ usage >&2
+ exit 2
+ EOF
+ fi
+}
+
+uuid() {
+ od -xN20 /dev/urandom |
+ head -n1 |
+ awk '{OFS="-"; print $2$3,$4,$5,$6,$7$8$9}'
+}
+
+tmpname() {
+ echo "${TMPDIR:-/tmp}/uuid-tmpname with spaces.$(uuid)"
+}
+
+mkstemp() {
+ name="$(tmpname)"
+ touch "$name"
+ echo "$name"
+}
+
+mkdtemp() {
+ name="$(tmpname)"
+ mkdir "$name"
+ echo "$name"
+}
diff --git a/share/aux-repo/aux/tld.txt b/share/aux-repo/aux/tld.txt
new file mode 100644
index 0000000..058a2d6
--- /dev/null
+++ b/share/aux-repo/aux/tld.txt
@@ -0,0 +1 @@
+euandre.org \ No newline at end of file
diff --git a/share/aux-repo/aux/workflow/TODOs.sh b/share/aux-repo/aux/workflow/TODOs.sh
new file mode 100755
index 0000000..8b06d15
--- /dev/null
+++ b/share/aux-repo/aux/workflow/TODOs.sh
@@ -0,0 +1,65 @@
+#!/bin/sh
+set -eu
+
+TLD="$(cat aux/tld.txt)"
+PROJECT_UC=
+while getopts 'n:N:m:o:' flag; do
+ case "$flag" in
+ n)
+ PROJECT="$OPTARG"
+ ;;
+ N)
+ PROJECT_UC="$OPTARG"
+ ;;
+ m)
+ MAILING_LIST="$OPTARG"
+ ;;
+ o)
+ OUTDIR="$OPTARG"
+ ;;
+ *)
+ exit 2
+ ;;
+ esac
+done
+shift $((OPTIND - 1))
+
+assert_arg() {
+ if [ -z "$1" ]; then
+ echo "Missing $2" >&2
+ exit 2
+ fi
+}
+
+assert_arg "${PROJECT:-}" '-n PROJECT'
+assert_arg "${MAILING_LIST:-}" '-m MAILING_LIST'
+assert_arg "${OUTDIR:-}" '-o OUTDIR'
+
+if [ -z "${PROJECT_UC:-}" ]; then
+ PROJECT_UC="$PROJECT"
+fi
+
+
+td -H |
+ cat aux/workflow/preamble.md - |
+ sed \
+ -e "s:@PROJECT_UC@:$PROJECT_UC:g" \
+ -e "s:@PROJECT@:$PROJECT:g" \
+ -e "s:@MAILING_LIST@:$MAILING_LIST:g" \
+ -e "s:@TLD@:$TLD:g" |
+ pandoc \
+ --toc \
+ --highlight-style pygments \
+ --toc-depth=2 \
+ -s \
+ --metadata title="$PROJECT_UC - TODOs" \
+ --metadata lang=en \
+ -r commonmark \
+ -w html \
+ -H aux/workflow/favicon.html \
+ -H aux/workflow/style.css |
+ sed \
+ -e 's:<a><a:<a:g' \
+ -e 's:</a></a>:</a>:g'
+
+# FIXME: check TODOs.sh from euandre.org
diff --git a/share/aux-repo/aux/workflow/favicon.svg b/share/aux-repo/aux/workflow/favicon.svg
new file mode 100644
index 0000000..ce566b2
--- /dev/null
+++ b/share/aux-repo/aux/workflow/favicon.svg
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16">
+ <path d="M 0 8 L 1 8 L 1 9 L 0 9 L 0 8 Z" />
+ <path d="M 0 13 L 1 13 L 1 14 L 0 14 L 0 13 Z" />
+ <path d="M 1 8 L 2 8 L 2 9 L 1 9 L 1 8 Z" />
+ <path d="M 1 13 L 2 13 L 2 14 L 1 14 L 1 13 Z" />
+ <path d="M 2 8 L 3 8 L 3 9 L 2 9 L 2 8 Z" />
+ <path d="M 2 13 L 3 13 L 3 14 L 2 14 L 2 13 Z" />
+ <path d="M 3 8 L 4 8 L 4 9 L 3 9 L 3 8 Z" />
+ <path d="M 3 13 L 4 13 L 4 14 L 3 14 L 3 13 Z" />
+ <path d="M 4 7 L 5 7 L 5 8 L 4 8 L 4 7 Z" />
+ <path d="M 4 8 L 5 8 L 5 9 L 4 9 L 4 8 Z" />
+ <path d="M 4 13 L 5 13 L 5 14 L 4 14 L 4 13 Z" />
+ <path d="M 5 6 L 6 6 L 6 7 L 5 7 L 5 6 Z" />
+ <path d="M 5 7 L 6 7 L 6 8 L 5 8 L 5 7 Z" />
+ <path d="M 5 13 L 6 13 L 6 14 L 5 14 L 5 13 Z" />
+ <path d="M 6 5 L 7 5 L 7 6 L 6 6 L 6 5 Z" />
+ <path d="M 6 6 L 7 6 L 7 7 L 6 7 L 6 6 Z" />
+ <path d="M 6 14 L 7 14 L 7 15 L 6 15 L 6 14 Z" />
+ <path d="M 7 1 L 8 1 L 8 2 L 7 2 L 7 1 Z" />
+ <path d="M 7 14 L 8 14 L 8 15 L 7 15 L 7 14 Z" />
+ <path d="M 7 15 L 8 15 L 8 16 L 7 16 L 7 15 Z" />
+ <path d="M 7 2 L 8 2 L 8 3 L 7 3 L 7 2 Z" />
+ <path d="M 7 3 L 8 3 L 8 4 L 7 4 L 7 3 Z" />
+ <path d="M 7 4 L 8 4 L 8 5 L 7 5 L 7 4 Z" />
+ <path d="M 7 5 L 8 5 L 8 6 L 7 6 L 7 5 Z" />
+ <path d="M 8 1 L 9 1 L 9 2 L 8 2 L 8 1 Z" />
+ <path d="M 8 15 L 9 15 L 9 16 L 8 16 L 8 15 Z" />
+ <path d="M 9 1 L 10 1 L 10 2 L 9 2 L 9 1 Z" />
+ <path d="M 9 2 L 10 2 L 10 3 L 9 3 L 9 2 Z" />
+ <path d="M 9 6 L 10 6 L 10 7 L 9 7 L 9 6 Z" />
+ <path d="M 9 15 L 10 15 L 10 16 L 9 16 L 9 15 Z" />
+ <path d="M 10 2 L 11 2 L 11 3 L 10 3 L 10 2 Z" />
+ <path d="M 10 3 L 11 3 L 11 4 L 10 4 L 10 3 Z" />
+ <path d="M 10 4 L 11 4 L 11 5 L 10 5 L 10 4 Z" />
+ <path d="M 10 5 L 11 5 L 11 6 L 10 6 L 10 5 Z" />
+ <path d="M 10 6 L 11 6 L 11 7 L 10 7 L 10 6 Z" />
+ <path d="M 11 6 L 12 6 L 12 7 L 11 7 L 11 6 Z" />
+ <path d="M 11 8 L 12 8 L 12 9 L 11 9 L 11 8 Z" />
+ <path d="M 10 15 L 11 15 L 11 16 L 10 16 L 10 15 Z" />
+ <path d="M 11 10 L 12 10 L 12 11 L 11 11 L 11 10 Z" />
+ <path d="M 11 12 L 12 12 L 12 13 L 11 13 L 11 12 Z" />
+ <path d="M 11 14 L 12 14 L 12 15 L 11 15 L 11 14 Z" />
+ <path d="M 11 15 L 12 15 L 12 16 L 11 16 L 11 15 Z" />
+ <path d="M 12 6 L 13 6 L 13 7 L 12 7 L 12 6 Z" />
+ <path d="M 12 8 L 13 8 L 13 9 L 12 9 L 12 8 Z" />
+ <path d="M 12 10 L 13 10 L 13 11 L 12 11 L 12 10 Z" />
+ <path d="M 12 12 L 13 12 L 13 13 L 12 13 L 12 12 Z" />
+ <path d="M 12 14 L 13 14 L 13 15 L 12 15 L 12 14 Z" />
+ <path d="M 13 6 L 14 6 L 14 7 L 13 7 L 13 6 Z" />
+ <path d="M 13 8 L 14 8 L 14 9 L 13 9 L 13 8 Z" />
+ <path d="M 13 10 L 14 10 L 14 11 L 13 11 L 13 10 Z" />
+ <path d="M 13 12 L 14 12 L 14 13 L 13 13 L 13 12 Z" />
+ <path d="M 13 13 L 14 13 L 14 14 L 13 14 L 13 13 Z" />
+ <path d="M 13 14 L 14 14 L 14 15 L 13 15 L 13 14 Z" />
+ <path d="M 14 7 L 15 7 L 15 8 L 14 8 L 14 7 Z" />
+ <path d="M 14 8 L 15 8 L 15 9 L 14 9 L 14 8 Z" />
+ <path d="M 14 9 L 15 9 L 15 10 L 14 10 L 14 9 Z" />
+ <path d="M 14 10 L 15 10 L 15 11 L 14 11 L 14 10 Z" />
+ <path d="M 14 11 L 15 11 L 15 12 L 14 12 L 14 11 Z" />
+ <path d="M 14 12 L 15 12 L 15 13 L 14 13 L 14 12 Z" />
+</svg>
diff --git a/share/aux-repo/aux/workflow/head.html b/share/aux-repo/aux/workflow/head.html
new file mode 100644
index 0000000..3902690
--- /dev/null
+++ b/share/aux-repo/aux/workflow/head.html
@@ -0,0 +1,2 @@
+<link rel="icon" href="favicon.svg" type="image/svg+xml" />
+<link rel="stylesheet" href="style.css" type="text/css" />
diff --git a/share/aux-repo/aux/workflow/md2html.sh b/share/aux-repo/aux/workflow/md2html.sh
new file mode 100755
index 0000000..957bfc2
--- /dev/null
+++ b/share/aux-repo/aux/workflow/md2html.sh
@@ -0,0 +1,87 @@
+#!/bin/sh
+set -eu
+
+. aux/lib.sh
+
+usage() {
+ cat <<-'EOF'
+ Usage:
+ aux/workflow/md2html.sh -N NAME_UC -T TITLE [-D TOC_DEPTH] < FILE.md
+ aux/workflow/md2html.sh -h
+ EOF
+}
+
+help() {
+ cat <<-'EOF'
+
+ Options:
+ -N NAME_UC the uppercased name of the project
+ -T TITLE the required title of the generated HTML
+ document
+ -D TOC_DEPTH the depth of the generated table of
+ contents (default: 2)
+ -h, --help show this message
+
+
+ Read markdown text from STDIN and emit HTML to STDOUT.
+ EOF
+}
+
+for flag in "$@"; do
+ case "$flag" in
+ --)
+ break
+ ;;
+ --help)
+ usage
+ help
+ exit
+ ;;
+ *)
+ ;;
+ esac
+done
+
+TOC_DEPTH=2
+while getopts 'N:T:D:h' flag; do
+ case "$flag" in
+ N)
+ NAME_UC="$OPTARG"
+ ;;
+ T)
+ TITLE="$OPTARG"
+ ;;
+ D)
+ TOC_DEPTH="$OPTARG"
+ ;;
+ h)
+ usage
+ help
+ exit
+ ;;
+ *)
+ usage >&2
+ exit 2
+ ;;
+ esac
+done
+shift $((OPTIND - 1))
+
+eval "$(assert_arg "${NAME_UC:-}" '-T TITLE')"
+eval "$(assert_arg "${TITLE:-}" '-T TITLE')"
+
+THE_LANG='en'
+
+ALTERNATES=/dev/null
+
+pandoc \
+ -s \
+ --toc \
+ --toc-depth="$TOC_DEPTH" \
+ --highlight-style=pygments \
+ --metadata lang="$THE_LANG" \
+ --metadata title="$TITLE - $NAME_UC" \
+ -r commonmark \
+ -w html \
+ -H aux/workflow/head.html \
+ -H "$ALTERNATES"
diff --git a/share/aux-repo/aux/workflow/preamble.md.in b/share/aux-repo/aux/workflow/preamble.md.in
new file mode 100644
index 0000000..1d17997
--- /dev/null
+++ b/share/aux-repo/aux/workflow/preamble.md.in
@@ -0,0 +1,16 @@
+# About
+
+TODOs for [@PROJECT_UC@](https://@TLD@/@PROJECT@/en/).
+
+Register a new one at
+<span id="new">[@MAILING_LIST@](mailto:@MAILING_LIST@?subject=%5B@PROJECT@%5D%20BUG%20or%20TASK%3A%20%3Cdescription%3E)</span>
+and see [existing discussions](@LIST_SEARCH@).
+
+*Você também pode escrever em português*.
+
+*Vous pouvez aussi écrire en français*.
+
+*Vi povas ankaŭ skribi esperante*.
+
+*Tu también puedes escribir en español*.
+
diff --git a/share/aux-repo/aux/workflow/style.css b/share/aux-repo/aux/workflow/style.css
new file mode 100644
index 0000000..4f3c83e
--- /dev/null
+++ b/share/aux-repo/aux/workflow/style.css
@@ -0,0 +1,80 @@
+html {
+ line-height: 1.5;
+}
+
+body {
+ max-width: 800px;
+ margin: 0 auto 0 auto;
+}
+
+hr {
+ background-color: #ccc;
+}
+
+.header-anchor {
+ opacity: 0.5;
+ display: inline-block;
+}
+
+.tag {
+ font-family: monospace;
+ font-size: 70%;
+ background-color: lightgray;
+ color: black;
+ padding: 3px;
+ border-radius: 5px;
+}
+
+.TODO {
+ color: brown;
+}
+
+.DOING {
+ color: yellowgreen;
+}
+
+.WAITING, .MEETING {
+ color: orange;
+}
+
+.INACTIVE {
+ color: gray;
+}
+
+.NEXT {
+ color: red;
+}
+
+.CANCELLED, .DONE, .WONTFIX {
+ color: green;
+}
+
+pre, code {
+ background-color: #ddd;
+ border-radius: 5px;
+ padding: 3px;
+}
+
+pre > code {
+ overflow: auto;
+ white-space: pre;
+}
+
+@media(prefers-color-scheme: dark) {
+ :root {
+ color: white;
+ background-color: black;
+ }
+
+ a {
+ color: hsl(211, 100%, 60%);
+ }
+
+ a:visited {
+ color: hsl(242, 100%, 80%);
+ }
+
+ pre, code {
+ background-color: #222;
+ }
+}