summaryrefslogtreecommitdiffstats
path: root/gen_web_hook.sh
diff options
context:
space:
mode:
Diffstat (limited to 'gen_web_hook.sh')
-rw-r--r--gen_web_hook.sh342
1 files changed, 342 insertions, 0 deletions
diff --git a/gen_web_hook.sh b/gen_web_hook.sh
new file mode 100644
index 0000000..050b89d
--- /dev/null
+++ b/gen_web_hook.sh
@@ -0,0 +1,342 @@
+#!/bin/bash
+# gen_web_hook.sh — generates static HTML header/footer files for the
+# Apache autoindex listing of the danix Slackware package repository.
+#
+# Can be called standalone or from slackrepo's HOOK_FINISH.
+# Usage: gen_web_hook.sh [/path/to/pkgrepo]
+#
+# If no argument is given, uses $SR_PKGREPO if set, otherwise /repo.
+
+set -euo pipefail
+
+PKGREPO="${1:-${SR_PKGREPO:-/repo}}"
+
+log() { echo "gen_web_hook: $*"; }
+warn() { echo "gen_web_hook: WARNING: $*" >&2; }
+
+if [ ! -d "$PKGREPO" ]; then
+ warn "PKGREPO '$PKGREPO' not found."
+ exit 1
+fi
+
+log "Generating static web files in $PKGREPO ..."
+
+# ── HTML escape ───────────────────────────────────────────────────────────────
+html_escape() {
+ local s="$1"
+ s="${s//&/&}"
+ s="${s//</&lt;}"
+ s="${s//>/&gt;}"
+ s="${s//\"/&quot;}"
+ printf '%s' "$s"
+}
+
+# ── Shared CSS ────────────────────────────────────────────────────────────────
+CSS='<style>
+:root {
+ --bg: #0e1117;
+ --bg-card: #161b25;
+ --bg-hover: #1e2535;
+ --border: #2a3147;
+ --accent: #5c9cf5;
+ --accent-dim:#3a5f99;
+ --green: #4ec97b;
+ --accent2: #4ec97b;
+ --text: #c9d1e0;
+ --text-dim: #6b7a99;
+ --text-head: #e8edf7;
+ --mono: "IBM Plex Mono", monospace;
+ --sans: "IBM Plex Sans", sans-serif;
+}
+*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
+body {
+ background: var(--bg); color: var(--text); font-family: var(--sans);
+ font-size: 15px; line-height: 1.6; min-height: 100vh;
+ display: flex; flex-direction: column;
+}
+.site-header { border-bottom: 1px solid var(--border); padding: 2rem 2.5rem 1.5rem; background: var(--bg-card); position: relative; overflow: hidden; }
+.header-top { display: flex; align-items: baseline; gap: 1rem; flex-wrap: wrap; margin-bottom: 0.5rem; }
+.site-title { font-family: var(--mono); font-size: 1.35rem; font-weight: 600; color: var(--text-head); }
+.site-title span { color: var(--accent); }
+.site-subtitle { font-size: 0.8rem; color: var(--text-dim); font-family: var(--mono); }
+.header-desc { font-size: 0.9rem; color: var(--text-dim); max-width: 65ch; margin-bottom: 1rem; }
+.header-links { display: flex; gap: 1.25rem; align-items: center; flex-wrap: wrap; }
+.header-links a {
+ font-family: var(--mono); font-size: 0.8rem; color: var(--accent); text-decoration: none;
+ border: 1px solid var(--accent-dim); padding: 0.2rem 0.65rem; border-radius: 3px;
+}
+.header-links a:hover { background: var(--accent); color: var(--bg); }
+pre { font-family: var(--mono) !important; color: var(--text) !important; background: transparent !important; padding: 1.5rem 2.5rem !important; flex: 1; }
+table { width: calc(100% - 5rem); margin: 1.5rem 2.5rem; border-collapse: collapse; font-family: var(--mono); font-size: 0.85rem; }
+th { text-align: left; color: var(--text-dim); font-weight: 600; font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.08em; padding: 0.5rem 0.75rem; border-bottom: 1px solid var(--border); }
+td { padding: 0.4rem 0.75rem; border-bottom: 1px solid rgba(42,49,71,0.5); vertical-align: middle; }
+tr:hover td { background: var(--bg-hover); }
+td a, td a:visited { color: var(--text-head); text-decoration: none; }
+td a[href$="/"]:not([href="../"]) { color: var(--accent); font-weight: 600; }
+td a:hover { color: var(--accent); text-decoration: underline; }
+td:nth-child(3), td:nth-child(4) { color: var(--text-dim); font-size: 0.8rem; }
+td a[href$=".txz"] { color: var(--green); font-weight: 600; }
+.autoindex-wrapper { flex: 1; display: flex; flex-direction: column; }
+hr { display: none; }
+address { display: none; }
+.pkg-info { margin: 0 2.5rem 1.5rem; border: 1px solid var(--border); border-radius: 6px; overflow: hidden; background: var(--bg-card); }
+.pkg-info-header { display: flex; align-items: baseline; gap: 0.75rem; padding: 0.6rem 1rem; background: rgba(92,156,245,0.06); border-bottom: 1px solid var(--border); }
+.pkg-info-label { font-family: var(--mono); font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.1em; color: var(--text-dim); }
+.pkg-info-name { font-family: var(--mono); font-size: 0.85rem; font-weight: 600; color: var(--accent); }
+.pkg-info-body { padding: 0.75rem 1rem; font-size: 0.875rem; line-height: 1.65; color: var(--text); }
+.pkg-info-body p { margin-bottom: 0.2rem; }
+.pkg-title { font-weight: 600; color: var(--text-head); margin-bottom: 0.5rem !important; }
+.pkg-meta { display: flex; gap: 1.5rem; flex-wrap: wrap; padding: 0.5rem 1rem; border-top: 1px solid var(--border); font-family: var(--mono); font-size: 0.75rem; }
+.pkg-meta em { font-style: normal; margin-right: 0.3rem; color: var(--text-dim); }
+.pkg-meta span { color: var(--text); }
+.pkg-homepage { padding: 0.4rem 1rem 0.6rem; font-family: var(--mono); font-size: 0.78rem; border-top: 1px solid var(--border); }
+.pkg-homepage a { color: var(--accent); text-decoration: none; }
+.pkg-homepage a:hover { text-decoration: underline; }
+.site-footer { border-top: 1px solid var(--border); background: var(--bg-card); padding: 1rem 2.5rem; margin-top: auto; }
+.footer-inner { display: flex; flex-direction: column; gap: 0.35rem; }
+.footer-meta { display: flex; align-items: center; gap: 1rem; margin-bottom: 0.2rem; }
+.footer-updated { font-family: var(--mono); font-size: 0.8rem; color: var(--text-dim); }
+.footer-date { color: var(--green); font-weight: 600; }
+.footer-rss { display: inline-flex; align-items: center; gap: 0.3rem; font-family: var(--mono); font-size: 0.75rem; color: #e8923a; text-decoration: none; border: 1px solid rgba(232,146,58,0.3); padding: 0.15rem 0.5rem; border-radius: 3px; }
+.footer-rss:hover { background: rgba(232,146,58,0.1); }
+.footer-sig { font-family: var(--mono); font-size: 0.75rem; color: var(--text-dim); display: flex; gap: 0.5rem; align-items: center; flex-wrap: wrap; }
+.footer-sig a { color: var(--accent); text-decoration: none; }
+.footer-sep { opacity: 0.3; }
+.category-pill { position: absolute; top: 50%; right: 2.5rem; transform: translateY(-50%); z-index: 2; background: var(--bg-card); border: 1px solid var(--border); border-radius: 999px; padding: 0.4rem 1.25rem; font-family: var(--mono); font-size: 1.4rem; font-weight: 700; letter-spacing: 0.02em; text-transform: capitalize; }
+.category-pill span { background: linear-gradient(135deg, var(--accent) 0%, var(--accent2) 100%); -webkit-background-clip: text; background-clip: text; color: transparent; }
+</style>'
+
+# ── Shared footer signature ───────────────────────────────────────────────────
+footer_sig() {
+ cat << 'EOF'
+<footer class="site-footer">
+ <div class="footer-inner">
+ <div class="footer-sig">
+ <span>danix packages &middot; Slackware64-current</span>
+ <span class="footer-sep">&middot;</span>
+ <a href="https://danix.xyz/is/here/">Contact danix</a>
+ <span class="footer-sep">&middot;</span>
+ <span>GPG signed &middot; use at your own risk</span>
+ </div>
+ </div>
+</footer>
+</body>
+</html>
+EOF
+}
+
+# ── Generate root _footer.html (last-updated + signature) ────────────────────
+generate_root_footer() {
+ local last_updated='unknown'
+ if [ -f "$PKGREPO/ChangeLog.txt" ]; then
+ last_updated=$(grep -m1 -E '^(Mon|Tue|Wed|Thu|Fri|Sat|Sun)' "$PKGREPO/ChangeLog.txt" || echo 'unknown')
+ fi
+
+ {
+ cat << EOF
+</div><!-- .autoindex-wrapper -->
+<footer class="site-footer">
+ <div class="footer-inner">
+ <div class="footer-meta">
+ <span class="footer-updated">Last updated:
+ <span class="footer-date">$(html_escape "$last_updated")</span>
+ </span>
+ <a class="footer-rss" href="/ChangeLog.rss">
+ <svg width="12" height="12" viewBox="0 0 24 24" fill="currentColor">
+ <circle cx="5" cy="19" r="3"/>
+ <path d="M4 4a16 16 0 0 1 16 16h-3A13 13 0 0 0 4 7z"/>
+ <path d="M4 11a9 9 0 0 1 9 9H10a6 6 0 0 0-6-6z"/>
+ </svg>
+ RSS feed
+ </a>
+ </div>
+ <div class="footer-sig">
+ <span>danix packages &middot; Slackware64-current</span>
+ <span class="footer-sep">&middot;</span>
+ <a href="https://danix.xyz/is/here/">Contact danix</a>
+ <span class="footer-sep">&middot;</span>
+ <span>GPG signed &middot; use at your own risk</span>
+ </div>
+ </div>
+</footer>
+</body>
+</html>
+EOF
+ } > "$PKGREPO/_footer.html"
+ log "Written: $PKGREPO/_footer.html"
+}
+
+# ── Generate per-package _footer.html ────────────────────────────────────────
+generate_package_footer() {
+ local pkg_dir="$1"
+ local pkg_name
+ pkg_name=$(basename "$pkg_dir")
+
+ local txt_file
+ txt_file=$(find "$pkg_dir" -maxdepth 1 -name '*.txt' | head -1)
+
+ if [ -z "$txt_file" ]; then
+ # No .txt file — minimal footer
+ { echo '</div><!-- .autoindex-wrapper -->'; footer_sig; } > "$pkg_dir/_footer.html"
+ return
+ fi
+
+ # Parse .txt
+ local title='' homepage='' body_lines=()
+ while IFS= read -r line; do
+ # Strip "pkgname:" or "pkgname: " prefix
+ local text
+ text=$(echo "$line" | sed 's/^[^:]*: \?//')
+ # Skip lines that were just "pkgname:" with nothing after
+ [[ "$line" == *: ]] && text=''
+ if [[ "$text" == Homepage:* ]]; then
+ homepage="${text#Homepage: }"
+ continue
+ fi
+ if [ -z "$title" ]; then
+ [ -n "$text" ] && title="$text"
+ else
+ [ -n "$text" ] && body_lines+=("$text")
+ fi
+ done < "$txt_file"
+
+ # Parse .meta for sizes
+ local meta_file size_c='' size_u=''
+ meta_file=$(find "$pkg_dir" -maxdepth 1 -name '*.meta' | head -1)
+ if [ -n "$meta_file" ]; then
+ size_c=$(grep 'PACKAGE SIZE (compressed):' "$meta_file" | sed 's/.*: *//')
+ size_u=$(grep 'PACKAGE SIZE (uncompressed):' "$meta_file" | sed 's/.*: *//')
+ fi
+
+ {
+ echo '</div><!-- .autoindex-wrapper -->'
+ echo '<section class="pkg-info">'
+ echo ' <div class="pkg-info-header">'
+ echo ' <span class="pkg-info-label">Package description</span>'
+ echo " <span class=\"pkg-info-name\">$(html_escape "$pkg_name")</span>"
+ echo ' </div>'
+ echo ' <div class="pkg-info-body">'
+ echo " <p class=\"pkg-title\">$(html_escape "$title")</p>"
+ for bline in "${body_lines[@]}"; do
+ echo " <p>$(html_escape "$bline")</p>"
+ done
+ echo ' </div>'
+
+ if [ -n "$size_c" ] || [ -n "$size_u" ]; then
+ echo ' <div class="pkg-meta">'
+ [ -n "$size_c" ] && echo " <span><em>Size (compressed):</em> $(html_escape "$size_c")</span>"
+ [ -n "$size_u" ] && echo " <span><em>Size (uncompressed):</em> $(html_escape "$size_u")</span>"
+ echo ' </div>'
+ fi
+
+ if [ -n "$homepage" ]; then
+ echo " <div class=\"pkg-homepage\"><a href=\"$(html_escape "$homepage")\" rel=\"noopener noreferrer\">$(html_escape "$homepage")</a></div>"
+ fi
+
+ echo '</section>'
+ footer_sig
+ } > "$pkg_dir/_footer.html"
+
+ log "Written: $pkg_dir/_footer.html"
+}
+
+# ── Write _header.html to a given directory ───────────────────────────────────
+write_header() {
+ local dir="$1"
+ cat > "$dir/_header.html" << EOF
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <title>danix Slackware Repository</title>
+ <link rel="preconnect" href="https://fonts.googleapis.com">
+ <link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;600&family=IBM+Plex+Sans:wght@300;400;600&display=swap" rel="stylesheet">
+ <script src="/.assets/matrix-rain.js" defer></script>
+ ${CSS}
+</head>
+<body>
+<header class="site-header">
+ <div class="header-top">
+ <div class="site-title"><span>//</span> <a href="https://packages.danix.xyz" style="color:var(--accent)">danix packages</a></div>
+ <div class="site-subtitle">Slackware64-current &middot; unofficial repository</div>
+ </div>
+ <p class="header-desc">
+ Third-party Slackware packages built with
+ <a href="https://github.com/aclemons/slackrepo" style="color:var(--accent)">slackrepo</a>
+ on Slackware64-current. Use at your own risk. All packages are signed with my GPG key.
+ </p>
+ <div class="header-links">
+ <a href="https://danix.xyz/is/here/">Contact me</a>
+ <a href="/ChangeLog.txt">ChangeLog</a>
+ <a href="/ChangeLog.rss">RSS</a>
+ </div>
+</header>
+<div class="autoindex-wrapper">
+EOF
+ log "Written: $dir/_header.html"
+}
+
+# ── Write _header.html for a category directory (includes pill) ───────────────
+write_category_header() {
+ local dir="$1"
+ local cat_name
+ cat_name=$(basename "$dir")
+ cat > "$dir/_header.html" << EOF
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <title>danix Slackware Repository</title>
+ <link rel="preconnect" href="https://fonts.googleapis.com">
+ <link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;600&family=IBM+Plex+Sans:wght@300;400;600&display=swap" rel="stylesheet">
+ <script src="/.assets/matrix-rain.js" defer></script>
+ ${CSS}
+</head>
+<body>
+<header class="site-header">
+ <div class="header-top">
+ <div class="site-title"><span>//</span> <a href="https://packages.danix.xyz" style="color:var(--accent)">danix packages</a></div>
+ <div class="site-subtitle">Slackware64-current &middot; unofficial repository</div>
+ </div>
+ <p class="header-desc">
+ Third-party Slackware packages built with
+ <a href="https://github.com/aclemons/slackrepo" style="color:var(--accent)">slackrepo</a>
+ on Slackware64-current. Use at your own risk. All packages are signed with my GPG key.
+ </p>
+ <div class="header-links">
+ <a href="https://danix.xyz/is/here/">Contact me</a>
+ <a href="/ChangeLog.txt">ChangeLog</a>
+ <a href="/ChangeLog.rss">RSS</a>
+ </div>
+ <div class="category-pill"><span>$(html_escape "$cat_name")</span></div>
+</header>
+<div class="autoindex-wrapper">
+EOF
+ log "Written: $dir/_header.html"
+}
+
+# ── Generate category _footer.html (just the signature) ──────────────────────
+generate_category_footer() {
+ local cat_dir="$1"
+ { echo '</div><!-- .autoindex-wrapper -->'; footer_sig; } > "$cat_dir/_footer.html"
+ log "Written: $cat_dir/_footer.html"
+}
+
+# ── Main ──────────────────────────────────────────────────────────────────────
+write_header "$PKGREPO"
+generate_root_footer
+
+for category in "$PKGREPO"/*/; do
+ [ -d "$category" ] || continue
+ write_category_header "$category"
+ generate_category_footer "$category"
+ for pkg in "$category"*/; do
+ [ -d "$pkg" ] || continue
+ write_header "$pkg"
+ generate_package_footer "$pkg"
+ done
+done
+
+log "Done."