splux-site · log · files · refs · tags · releases · people · languages · GitHub · file
tools/git.awk
15498 bytes at 4c4f12c · GitHub
# HTML fragments for the static Splux Git browser.
# mode=one escape $0 (or -v text=) as one HTML string
# mode=who -v login= -v name= -v avatar= -v verified= -v userpfx=
# mode=pre escape stdin as a <pre class="block git-blob">
# mode=langs TSV lang<TAB>bytes<TAB>color[<TAB>nfiles]
# -v langpfx=
# mode=langindex TSV lang<TAB>ghbytes<TAB>color<TAB>nfiles<TAB>filebytes
# -v langpfx=
# mode=commits TSV hash short epoch iso subject author login avatar verified [repo]
# -v commitpfx= -v userpfx= -v repopfx=
# mode=people TSV login avatar count [name]
# -v userpfx=
# mode=peoplelist TSV login avatar count name iso subject hash
# -v userpfx= -v commitpfx=
# mode=entries TSV kind size name href [lang]
# -v langpfx= -v showlang=no
# mode=tags TSV name sha short iso kind subject rel [seg]
# -v tagpfx= -v commitpfx= -v relpfx=
# mode=releases TSV tag title iso login avatar pre latest nassets excerpt reactions [seg]
# -v relpfx= -v tagpfx= -v userpfx=
# mode=assets TSV name size downloads url [type]
# mode=notes release body as text; light markdown (lists, headings, code, links)
function esc(s) {
gsub(/&/, "\\&", s)
gsub(/</, "\\<", s)
gsub(/>/, "\\>", s)
gsub(/"/, "\\"", s)
return s
}
function pct(n, d) {
if (d <= 0)
return 0
return int((n * 1000 + d / 2) / d) / 10
}
function slug(s) {
gsub(/[ \/]/, "-", s)
return s
}
function langhref(name) {
if (langpfx == "" || name == "")
return ""
return langpfx slug(name) "/"
}
function humansize(n, mb) {
n = n + 0
if (n >= 1073741824)
return sprintf("%.1f GB", n / 1073741824)
if (n >= 1048576) {
mb = n / 1048576
if (mb >= 10)
return sprintf("%.0f MB", mb)
return sprintf("%.1f MB", mb)
}
if (n >= 1024)
return sprintf("%.0f KB", n / 1024)
if (n > 0)
return n " B"
return "0 B"
}
function autolink(s, out, url) {
out = ""
while (match(s, /https:\/\/[^[:space:]<>"']+/)) {
url = substr(s, RSTART, RLENGTH)
out = out substr(s, 1, RSTART - 1) "<a href=\"" url "\">" url "</a>"
s = substr(s, RSTART + RLENGTH)
}
return out s
}
function inline(s, out, code) {
s = esc(s)
out = ""
while (match(s, /`[^`]+`/)) {
code = substr(s, RSTART + 1, RLENGTH - 2)
out = out substr(s, 1, RSTART - 1) "<code>" code "</code>"
s = substr(s, RSTART + RLENGTH)
}
return autolink(out s)
}
function notes_flush_p() {
if (para != "") {
print "<p>" inline(para) "</p>"
para = ""
any = 1
}
}
function notes_flush_ul() {
if (inul) {
print "</ul>"
inul = 0
any = 1
}
}
function who(login, name, avatar, html, av, label) {
label = login != "" ? login : name
if (login != "") {
av = avatar
if (av == "")
av = "https://github.com/" login ".png?size=48"
html = "<a class=\"who\" href=\"" userpfx esc(login) "/\">"
html = html "<img class=\"avatar\" src=\"" esc(av) \
"\" width=\"24\" height=\"24\" alt=\"\" loading=\"lazy\">"
html = html esc(login) "</a>"
return html
}
return esc(name)
}
BEGIN {
FS = "\t"
limit = limit + 0
if (userpfx == "")
userpfx = "../../../../../git/users/"
if (mode == "one") {
if (text != "")
printf "%s", esc(text)
else {
while ((getline line) > 0)
printf "%s", esc(line)
}
exit
}
if (mode == "who") {
printf "%s", who(login, name, avatar)
if (verified == "yes")
printf " <span class=\"verified\">verified</span>"
exit
}
}
mode == "pre" {
if (!opened) {
print "<pre class=\"block git-blob\">"
opened = 1
}
print esc($0)
}
mode == "langs" {
n++
lang[n] = $1
bytes[n] = $2 + 0
col[n] = $3
nfiles[n] = $4 + 0
total += bytes[n]
}
mode == "langindex" {
n++
lang[n] = $1
bytes[n] = $2 + 0
col[n] = $3
nfiles[n] = $4 + 0
fbytes[n] = $5 + 0
total += (bytes[n] > 0) ? bytes[n] : fbytes[n]
}
mode == "commits" {
if (limit > 0 && n >= limit)
next
n++
hash[n] = $1
short[n] = $2
iso[n] = $4
subject[n] = $5
author[n] = $6
login[n] = $7
avatar[n] = $8
verified[n] = $9
repo[n] = $10
}
mode == "people" {
n++
login[n] = $1
avatar[n] = $2
count[n] = $3
pname[n] = $4
}
mode == "peoplelist" {
n++
login[n] = $1
avatar[n] = $2
count[n] = $3
pname[n] = $4
iso[n] = $5
subject[n] = $6
hash[n] = $7
}
mode == "entries" {
n++
kind[n] = $1
size[n] = $2
name[n] = $3
href[n] = $4
elang[n] = $5
}
mode == "tags" {
n++
name[n] = $1
hash[n] = $2
short[n] = $3
iso[n] = $4
kind[n] = $5
subject[n] = $6
rel[n] = $7
tseg[n] = ($8 != "") ? $8 : $1
}
mode == "releases" {
n++
rtag[n] = $1
title[n] = $2
iso[n] = $3
login[n] = $4
avatar[n] = $5
pre[n] = $6
latest[n] = $7
nassets[n] = $8
excerpt[n] = $9
react[n] = $10
rseg[n] = ($11 != "") ? $11 : $1
}
mode == "assets" {
n++
name[n] = $1
size[n] = $2
count[n] = $3
href[n] = $4
kind[n] = $5
}
mode == "notes" {
line = $0
sub(/\r$/, "", line)
if (line ~ /^```/) {
notes_flush_p()
notes_flush_ul()
if (inpre) {
print "</pre>"
inpre = 0
} else {
print "<pre class=\"block\">"
inpre = 1
}
any = 1
next
}
if (inpre) {
print esc(line)
any = 1
next
}
if (line ~ /^### /) {
notes_flush_p()
notes_flush_ul()
print "<h4>" inline(substr(line, 5)) "</h4>"
any = 1
next
}
if (line ~ /^## /) {
notes_flush_p()
notes_flush_ul()
print "<h3>" inline(substr(line, 4)) "</h3>"
any = 1
next
}
if (line ~ /^# /) {
notes_flush_p()
notes_flush_ul()
print "<h3>" inline(substr(line, 3)) "</h3>"
any = 1
next
}
if (line ~ /^- / || line ~ /^\* /) {
notes_flush_p()
if (!inul) {
print "<ul class=\"plain\">"
inul = 1
}
print "<li>" inline(substr(line, 3)) "</li>"
any = 1
next
}
if (line ~ /^[[:space:]]*$/) {
notes_flush_p()
notes_flush_ul()
next
}
notes_flush_ul()
if (para != "")
para = para " " line
else
para = line
}
END {
if (mode == "notes") {
if (inpre)
print "</pre>"
notes_flush_p()
notes_flush_ul()
if (!any)
print "<p class=\"muted\">No notes.</p>"
exit
}
if (mode == "pre") {
if (!opened)
print "<pre class=\"block git-blob\"></pre>"
else
print "</pre>"
exit
}
if (mode == "langs") {
if (n < 1)
exit
print "<div class=\"lang-bar\" role=\"img\" aria-label=\"Languages\">"
for (i = 1; i <= n; i++) {
w = pct(bytes[i], total)
if (w <= 0 && bytes[i] > 0)
w = 0.1
style = "width:" w "%"
if (col[i] != "")
style = style ";background:" col[i]
href = langhref(lang[i])
title = esc(lang[i]) " " w "%"
if (href != "")
printf "<a class=\"lang-seg\" href=\"%s\" style=\"%s\" title=\"%s\"></a>\n", \
esc(href), style, title
else
printf "<span class=\"lang-seg\" style=\"%s\" title=\"%s\"></span>\n", \
style, title
}
print "</div>"
print "<ul class=\"lang-list\">"
for (i = 1; i <= n; i++) {
href = langhref(lang[i])
dot = esc(col[i] != "" ? col[i] : "#888888")
extra = pct(bytes[i], total) "%"
if (nfiles[i] > 0)
extra = extra " · " nfiles[i] " files"
if (href != "")
printf "<li><a href=\"%s\"><span class=\"lang-dot\" style=\"background:%s\"></span> %s <span class=\"muted\">%s</span></a></li>\n", \
esc(href), dot, esc(lang[i]), extra
else
printf "<li><span class=\"lang-dot\" style=\"background:%s\"></span> %s <span class=\"muted\">%s</span></li>\n", \
dot, esc(lang[i]), extra
}
print "</ul>"
exit
}
if (mode == "langindex") {
print "<table class=\"pkgs git-langs\" id=\"git-lang-table\">"
print "<thead><tr><th>Language</th><th>Files</th><th>Bytes</th><th></th></tr></thead>"
print "<tbody>"
for (i = 1; i <= n; i++) {
href = langhref(lang[i])
dot = esc(col[i] != "" ? col[i] : "#888888")
sz = bytes[i] > 0 ? bytes[i] : fbytes[i]
w = pct(sz, total)
printf "<tr data-search=\"%s\">", esc(tolower(lang[i]))
printf "<td>"
if (href != "")
printf "<a href=\"%s\"><span class=\"lang-dot\" style=\"background:%s\"></span> %s</a>", \
esc(href), dot, esc(lang[i])
else
printf "<span class=\"lang-dot\" style=\"background:%s\"></span> %s", \
dot, esc(lang[i])
printf "</td>"
printf "<td class=\"muted\">%s</td>", (nfiles[i] > 0 ? nfiles[i] : "")
printf "<td class=\"muted\">%s</td>", (sz > 0 ? sz : "")
printf "<td class=\"muted\">%s%%</td>", w
print "</tr>"
}
print "</tbody></table>"
exit
}
if (mode == "commits") {
print "<table class=\"pkgs git-log\">"
if (repopfx != "")
print "<thead><tr><th>Commit</th><th>Repository</th><th>Subject</th><th>Author</th><th>When</th></tr></thead>"
else
print "<thead><tr><th>Commit</th><th>Subject</th><th>Author</th><th>When</th></tr></thead>"
print "<tbody>"
for (i = 1; i <= n; i++) {
day = iso[i]
sub(/T.*/, "", day)
if (repopfx != "" && repo[i] != "")
href = repopfx esc(repo[i]) "/commit/" esc(hash[i]) "/"
else
href = commitpfx esc(hash[i]) "/"
printf "<tr data-sha=\"%s\" data-login=\"%s\" data-repo=\"%s\">", \
esc(hash[i]), esc(login[i]), esc(repo[i])
printf "<td><a href=\"%s\"><code>%s</code></a></td>", href, esc(short[i])
if (repopfx != "" && repo[i] != "")
printf "<td><a href=\"%s%s/\">%s</a></td>", \
repopfx, esc(repo[i]), esc(repo[i])
printf "<td><a href=\"%s\">%s</a></td>", href, esc(subject[i])
printf "<td>%s", who(login[i], author[i], avatar[i])
if (verified[i] == "yes")
printf " <span class=\"verified\">verified</span>"
printf "</td>"
printf "<td><time datetime=\"%s\">%s</time></td>", esc(iso[i]), esc(day)
print "</tr>"
}
print "</tbody></table>"
exit
}
if (mode == "people") {
print "<div class=\"people\" id=\"git-people\">"
for (i = 1; i <= n; i++) {
label = pname[i] != "" ? pname[i] : login[i]
printf "<span class=\"person\">%s", who(login[i], label, avatar[i])
if (count[i] != "")
printf " <span class=\"muted\">%s</span>", esc(count[i])
print "</span>"
}
print "</div>"
exit
}
if (mode == "peoplelist") {
print "<table class=\"pkgs git-people\" id=\"git-people-table\">"
print "<thead><tr><th>Person</th><th>Commits</th><th>Last commit</th><th>When</th></tr></thead>"
print "<tbody>"
for (i = 1; i <= n; i++) {
label = pname[i] != "" ? pname[i] : login[i]
search = tolower(login[i] " " label)
printf "<tr data-login=\"%s\" data-search=\"%s\">", \
esc(login[i]), esc(search)
printf "<td>%s</td>", who(login[i], label, avatar[i])
printf "<td class=\"muted\">%s</td>", esc(count[i])
if (hash[i] != "" && commitpfx != "") {
chref = commitpfx esc(hash[i]) "/"
printf "<td><a href=\"%s\">%s</a></td>", chref, esc(subject[i])
} else
printf "<td>%s</td>", esc(subject[i])
day = iso[i]
sub(/T.*/, "", day)
if (iso[i] != "")
printf "<td><time datetime=\"%s\">%s</time></td>", \
esc(iso[i]), esc(day)
else
printf "<td></td>"
print "</tr>"
}
print "</tbody></table>"
exit
}
if (mode == "entries") {
print "<table class=\"pkgs git-tree\">"
if (showlang == "no")
print "<thead><tr><th></th><th>Name</th><th>Size</th></tr></thead>"
else
print "<thead><tr><th></th><th>Name</th><th>Language</th><th>Size</th></tr></thead>"
print "<tbody>"
for (i = 1; i <= n; i++) {
label = kind[i] == "dir" ? "dir" : "file"
sz = kind[i] == "dir" ? "" : size[i]
printf "<tr data-search=\"%s %s\">", esc(tolower(name[i])), esc(tolower(elang[i]))
printf "<td class=\"muted\">%s</td>", label
printf "<td><a href=\"%s\">%s</a></td>", esc(href[i]), esc(name[i])
if (showlang != "no") {
lhref = langhref(elang[i])
if (lhref != "" && elang[i] != "")
printf "<td><a href=\"%s\">%s</a></td>", esc(lhref), esc(elang[i])
else
printf "<td class=\"muted\">%s</td>", esc(elang[i])
}
printf "<td class=\"muted\">%s</td>", esc(sz)
print "</tr>"
}
print "</tbody></table>"
exit
}
if (mode == "tags") {
if (n < 1) {
print "<p class=\"muted\">No tags in this tree.</p>"
exit
}
print "<table class=\"pkgs git-tags\" id=\"git-tag-table\">"
print "<thead><tr><th>Tag</th><th>Commit</th><th>When</th><th>Message</th><th></th></tr></thead>"
print "<tbody>"
for (i = 1; i <= n; i++) {
thref = (tagpfx != "") ? tagpfx esc(tseg[i]) "/" : ""
chref = (commitpfx != "" && hash[i] != "") ? commitpfx esc(hash[i]) "/" : ""
rhref = (relpfx != "" && rel[i] != "") ? relpfx esc(tseg[i]) "/" : ""
search = tolower(name[i] " " subject[i] " " kind[i])
printf "<tr data-tag=\"%s\" data-sha=\"%s\" data-search=\"%s\">", \
esc(name[i]), esc(hash[i]), esc(search)
printf "<td>"
if (thref != "")
printf "<a href=\"%s\"><code>%s</code></a>", thref, esc(name[i])
else
printf "<code>%s</code>", esc(name[i])
printf "</td>"
printf "<td>"
if (chref != "")
printf "<a href=\"%s\"><code>%s</code></a>", chref, esc(short[i])
else
printf "<code>%s</code>", esc(short[i])
printf "</td>"
day = iso[i]
sub(/T.*/, "", day)
if (iso[i] != "")
printf "<td><time datetime=\"%s\">%s</time></td>", \
esc(iso[i]), esc(day)
else
printf "<td></td>"
printf "<td>%s</td>", esc(subject[i])
printf "<td>"
if (kind[i] == "annotated")
printf "<span class=\"badge\">annotated</span> "
if (rhref != "")
printf "<a href=\"%s\">release</a>", rhref
print "</td></tr>"
}
print "</tbody></table>"
exit
}
if (mode == "releases") {
if (n < 1) {
print "<p class=\"muted\">No GitHub releases yet.</p>"
exit
}
print "<div class=\"release-list\" id=\"git-releases\">"
for (i = 1; i <= n; i++) {
thref = (tagpfx != "") ? tagpfx esc(rseg[i]) "/" : ""
rhref = (relpfx != "") ? relpfx esc(rseg[i]) "/" : ""
search = tolower(rtag[i] " " title[i] " " login[i])
printf "<article class=\"release\" data-tag=\"%s\" data-search=\"%s\">\n", \
esc(rtag[i]), esc(search)
printf "<p class=\"meta\">"
if (latest[i] == "yes")
printf "<span class=\"badge latest\">Latest</span> "
if (pre[i] == "yes")
printf "<span class=\"badge\">Pre-release</span> "
if (iso[i] != "") {
day = iso[i]
sub(/T.*/, "", day)
printf "<time datetime=\"%s\">%s</time> ", esc(iso[i]), esc(day)
}
printf "%s", who(login[i], login[i], avatar[i])
print "</p>"
printf "<h3>"
if (rhref != "")
printf "<a href=\"%s\">%s</a>", rhref, esc(title[i])
else
printf "%s", esc(title[i])
print "</h3>"
printf "<p class=\"muted\">"
if (thref != "")
printf "<a href=\"%s\"><code>%s</code></a>", thref, esc(rtag[i])
else
printf "<code>%s</code>", esc(rtag[i])
if (nassets[i] + 0 > 0)
printf " · %s files", esc(nassets[i])
if (react[i] + 0 > 0)
printf " · %s reactions", esc(react[i])
print "</p>"
if (excerpt[i] != "")
printf "<p class=\"summary\">%s</p>\n", esc(excerpt[i])
print "</article>"
}
print "</div>"
exit
}
if (mode == "assets") {
if (n < 1) {
print "<p class=\"muted\">No files attached.</p>"
exit
}
print "<table class=\"pkgs git-assets\" id=\"git-asset-table\">"
print "<thead><tr><th>File</th><th>Size</th><th>Downloads</th></tr></thead>"
print "<tbody>"
for (i = 1; i <= n; i++) {
search = tolower(name[i] " " kind[i])
printf "<tr data-search=\"%s\">", esc(search)
printf "<td><a href=\"%s\">%s</a></td>", esc(href[i]), esc(name[i])
printf "<td class=\"muted\">%s</td>", esc(humansize(size[i]))
printf "<td class=\"muted\">%s</td>", esc(count[i])
print "</tr>"
}
print "</tbody></table>"
exit
}
}