splux-site · log · files · refs · tags · releases · people · languages · GitHub · commit
418381a
Show GitHub profile pictures next to news authors.
Parents
Stat
site/assets/live.js | 29 ++++++++++++++++++++++++++--- site/assets/style.css | 12 ++++++++++++ tools/collect-news.sh | 37 +++++++++++++++++++++++++++---------- tools/news.awk | 24 ++++++++++++++++-------- 4 files changed, 81 insertions(+), 21 deletions(-)
Diff
diff --git a/site/assets/live.js b/site/assets/live.js
index df85ab0..7b94072 100644
--- a/site/assets/live.js
+++ b/site/assets/live.js
@@ -117,6 +117,7 @@
repo: a.getAttribute("data-repo") || "",
author: a.getAttribute("data-author") || "",
verified: a.getAttribute("data-verified") === "yes",
+ avatar: a.getAttribute("data-avatar") || "",
url: link.getAttribute("href") || "",
title: link.textContent || "",
summary: summary ? summary.textContent : ""
@@ -139,6 +140,7 @@
repo: it.repo || "",
author: it.author || "",
verified: !!it.verified,
+ avatar: it.avatar || "",
url: it.url,
title: it.title || "",
summary: it.summary || ""
@@ -147,16 +149,35 @@
return items;
}
+ function avatarOf(it) {
+ var av = it && it.avatar ? String(it.avatar) : "";
+ if (/^https:\/\/(avatars\.githubusercontent\.com\/|github\.com\/)/.test(av))
+ return av;
+ var name = it && it.author ? String(it.author) : "";
+ if (/^[A-Za-z0-9-]+$/.test(name))
+ return "https://github.com/" + name + ".png?size=48";
+ return "";
+ }
+
function renderItem(it, hideSummary) {
+ var av = avatarOf(it);
var html = "<article class=\"item\" data-kind=\"" + esc(it.kind || "") +
"\" data-repo=\"" + esc(it.repo || "") +
"\" data-author=\"" + esc(it.author || "") +
- "\" data-verified=\"" + (it.verified ? "yes" : "no") + "\">";
+ "\" data-verified=\"" + (it.verified ? "yes" : "no") +
+ "\" data-avatar=\"" + esc(av) + "\">";
html += "<p class=\"meta\"><time datetime=\"" + esc(it.iso) + "\">" +
esc(formatLocal(it.iso)) + "</time> <span class=\"kind\">" +
esc(it.kind) + "</span> " + esc(it.repo);
- if (it.author)
- html += " <span class=\"who\">" + esc(it.author) + "</span>";
+ if (it.author || av) {
+ html += " <span class=\"who\">";
+ if (av)
+ html += "<img class=\"avatar\" src=\"" + esc(av) +
+ "\" width=\"24\" height=\"24\" alt=\"\" loading=\"lazy\">";
+ if (it.author)
+ html += esc(it.author);
+ html += "</span>";
+ }
if (it.verified)
html += " <span class=\"verified\">verified</span>";
html += "</p>";
@@ -324,6 +345,7 @@
repo: "SPS",
author: (r.author && r.author.login) || "",
verified: false,
+ avatar: (r.author && r.author.avatar_url) || "",
url: r.html_url || "",
title: r.name || r.tag_name || "",
summary: body
@@ -350,6 +372,7 @@
repo: label,
author: author,
verified: !!ver.verified,
+ avatar: (c.author && c.author.avatar_url) || "",
url: c.html_url || "",
title: firstLine(commit.message),
summary: ""
diff --git a/site/assets/style.css b/site/assets/style.css
index 6421253..2a76132 100644
--- a/site/assets/style.css
+++ b/site/assets/style.css
@@ -279,9 +279,21 @@ footer p {
}
.feed .who {
+ display: inline-flex;
+ align-items: center;
+ gap: 0.35rem;
color: var(--fg);
}
+.feed .avatar {
+ display: block;
+ width: 24px;
+ height: 24px;
+ border: 1px solid var(--rule);
+ background: #111;
+ flex-shrink: 0;
+}
+
.feed .verified {
display: inline-block;
color: var(--accent);
diff --git a/tools/collect-news.sh b/tools/collect-news.sh
index 11ffa3f..7b78130 100755
--- a/tools/collect-news.sh
+++ b/tools/collect-news.sh
@@ -1,6 +1,6 @@
#!/bin/sh
# Collect Splux releases and git history into TSV for the news page.
-# Fields: epoch iso kind repo url title summary author verified
+# Fields: epoch iso kind repo url title summary author verified avatar
# Env: CORE EXTRA SPS SITE (git work trees). GH_TOKEN optional via gh.
# Pulls every non-draft SPS release and every commit available from the
# local clones and from the GitHub API. Duplicate URLs keep the last row
@@ -29,16 +29,30 @@ emit() {
summary=${7-}
author=${8-}
verified=${9-}
+ avatar=${10-}
title=$(printf '%s' "$title" | tr '\t\r\n' ' ')
summary=$(printf '%s' "$summary" | tr '\t\r\n' ' ')
author=$(printf '%s' "$author" | tr '\t\r\n' ' ')
+ avatar=$(printf '%s' "$avatar" | tr '\t\r\n' ' ')
case $verified in
yes|no) ;;
*) verified= ;;
esac
- printf '%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n' \
+ case $avatar in
+ https://avatars.githubusercontent.com/*|https://github.com/*.png*) ;;
+ *) avatar=$(github_avatar "$author") ;;
+ esac
+ printf '%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n' \
"$epoch" "$iso" "$kind" "$repo" "$url" "$title" "$summary" \
- "$author" "$verified" >>"$out"
+ "$author" "$verified" "$avatar" >>"$out"
+}
+
+github_avatar() {
+ login=$1
+ case $login in
+ ""|*[!A-Za-z0-9-]*) ;;
+ *) printf 'https://github.com/%s.png?size=48' "$login" ;;
+ esac
}
epoch_of() {
@@ -67,21 +81,22 @@ git_commits() {
[ -n "${iso-}" ] || continue
[ -n "${hash-}" ] || continue
emit "$epoch" "$iso" commit "$repo" \
- "$baseurl/commit/$hash" "$subject" "" "$author" ""
+ "$baseurl/commit/$hash" "$subject" "" "$author" "" \
+ "$(github_avatar "$author")"
done
}
read_commit_tsv() {
repo=$1
file=$2
- while IFS=$tab read -r published url title author verified || [ -n "${published-}" ]
+ while IFS=$tab read -r published url title author verified avatar || [ -n "${published-}" ]
do
[ -n "${published-}" ] || continue
[ -n "${url-}" ] || continue
[ -n "${title-}" ] || title=$url
epoch=$(epoch_of "$published")
emit "$epoch" "$published" commit "$repo" "$url" "$title" "" \
- "$author" "$verified"
+ "$author" "$verified" "$avatar"
done <"$file"
}
@@ -97,16 +112,17 @@ if command -v gh >/dev/null 2>&1; then
.html_url,
((.name // .tag_name) | gsub("[\r\t]"; " ")),
((.body // "") | gsub("[\r\t]"; " ") | gsub("\n+"; " ") | .[0:900]),
- ((.author.login // "") | gsub("[\r\t]"; " "))
+ ((.author.login // "") | gsub("[\r\t]"; " ")),
+ ((.author.avatar_url // "") | gsub("[\r\t]"; " "))
] | @tsv' >"$tmp/rel"
then
- while IFS=$tab read -r published url name body author || [ -n "${published-}" ]
+ while IFS=$tab read -r published url name body author avatar || [ -n "${published-}" ]
do
[ -n "${published-}" ] || continue
[ -n "${url-}" ] || continue
epoch=$(epoch_of "$published")
emit "$epoch" "$published" release SPS "$url" "$name" "$body" \
- "$author" ""
+ "$author" "" "$avatar"
done <"$tmp/rel"
else
printf '%s\n' "collect-news: GitHub releases request failed" >&2
@@ -121,7 +137,8 @@ if command -v gh >/dev/null 2>&1; then
.html_url,
((.commit.message // "") | split("\n")[0] | gsub("[\r\t]"; " ")),
((.author.login // .commit.author.name // "") | gsub("[\r\t]"; " ")),
- (if .commit.verification.verified == true then "yes" else "no" end)
+ (if .commit.verification.verified == true then "yes" else "no" end),
+ ((.author.avatar_url // "") | gsub("[\r\t]"; " "))
] | @tsv' >"$tmp/c"
then
read_commit_tsv "$label" "$tmp/c"
diff --git a/tools/news.awk b/tools/news.awk
index af2d0c1..75c3a05 100644
--- a/tools/news.awk
+++ b/tools/news.awk
@@ -1,5 +1,5 @@
# Turn collect-news.sh TSV into HTML, a pager, JSON, or Atom.
-# Fields: epoch iso kind repo url title summary author verified
+# Fields: epoch iso kind repo url title summary author verified avatar
# -v mode=html|brief|atom|json|pager
# -v page= -v per= -v pages= -v nest=0|1 -v siteurl= -v feedupdated=
@@ -73,6 +73,7 @@ function page_href(p) {
summary[n] = $7
author[n] = $8
verified[n] = $9
+ avatar[n] = $10
}
END {
@@ -112,17 +113,24 @@ END {
print "</div>"
}
-function print_item(i, brief, k, when, s, v, a) {
+function print_item(i, brief, k, when, s, v, a, av) {
when = esc(utc_label(iso[i]))
k = esc(kind_label(kind[i]))
a = author[i]
v = verified[i]
- printf "<article class=\"item\" data-kind=\"%s\" data-repo=\"%s\" data-author=\"%s\" data-verified=\"%s\">\n", \
- k, esc(repo[i]), esc(a), esc(v)
+ av = avatar[i]
+ printf "<article class=\"item\" data-kind=\"%s\" data-repo=\"%s\" data-author=\"%s\" data-verified=\"%s\" data-avatar=\"%s\">\n", \
+ k, esc(repo[i]), esc(a), esc(v), esc(av)
printf "<p class=\"meta\"><time datetime=\"%s\">%s</time> <span class=\"kind\">%s</span> %s", \
esc(iso[i]), when, k, esc(repo[i])
- if (a != "")
- printf " <span class=\"who\">%s</span>", esc(a)
+ if (a != "" || av != "") {
+ printf " <span class=\"who\">"
+ if (av != "")
+ printf "<img class=\"avatar\" src=\"%s\" width=\"24\" height=\"24\" alt=\"\" loading=\"lazy\">", esc(av)
+ if (a != "")
+ printf "%s", esc(a)
+ printf "</span>"
+ }
if (v == "yes")
printf " <span class=\"verified\">verified</span>"
print "</p>"
@@ -200,10 +208,10 @@ function print_json( i, v) {
if (i > 1)
print ","
v = (verified[i] == "yes") ? "true" : "false"
- printf "{\"iso\":\"%s\",\"kind\":\"%s\",\"repo\":\"%s\",\"url\":\"%s\",\"title\":\"%s\",\"summary\":\"%s\",\"author\":\"%s\",\"verified\":%s}", \
+ printf "{\"iso\":\"%s\",\"kind\":\"%s\",\"repo\":\"%s\",\"url\":\"%s\",\"title\":\"%s\",\"summary\":\"%s\",\"author\":\"%s\",\"verified\":%s,\"avatar\":\"%s\"}", \
jesc(iso[i]), jesc(kind_label(kind[i])), jesc(repo[i]), \
jesc(url[i]), jesc(title[i]), jesc(summary[i]), \
- jesc(author[i]), v
+ jesc(author[i]), v, jesc(avatar[i])
}
print "\n]"
}