@@ -57,20 +57,23 @@ jobs:
5757 env :
5858 REPO_HTML_TITLE : ${{ github.repository }}
5959 OWNER : ${{ github.repository_owner }}
60- REPO_FULL : ${{ github.repository }}
60+ REPO_FULL : ${{ github.repository }} # owner/repo
6161 run : |
6262 set -e
6363 GENERATED=0
6464
6565 # === Compute dynamic URLs ===
6666 REPO_NAME="${REPO_FULL#*/}"
6767 REPO_URL="https://github.com/${REPO_FULL}"
68+
69+ # Pages URL: special-case owner.github.io
6870 if [ "$REPO_NAME" = "${OWNER}.github.io" ]; then
6971 PAGES_URL="https://${OWNER}.github.io/"
7072 else
7173 PAGES_URL="https://${OWNER}.github.io/${REPO_NAME}/"
7274 fi
7375
76+ # Minimal Pandoc template (no default CSS)
7477 cat > pandoc_template.html <<'TPL'
7578 <!doctype html>
7679 <html>
@@ -94,24 +97,77 @@ jobs:
9497 if [ -f index.html ]; then
9598 echo "Keeping existing index.html (not regenerating)."
9699 elif [ -f README.md ]; then
100+ echo "Generating index.html from README.md..."
97101 pandoc README.md -f markdown -t html -s \
98102 --template=pandoc_template.html \
99103 -o index.html \
100104 --metadata title="$REPO_HTML_TITLE"
101105 GENERATED=1
102106 else
107+ echo "No index.html or README.md found; writing minimal page."
103108 printf '%s\n' '<!doctype html><html><head><meta charset="utf-8"><title>Site</title></head><body>' '<h1>Site</h1>' '<p>No README.md found. Add one and push to regenerate this page.</p>' '</body></html>' > index.html
104109 GENERATED=1
105110 fi
106111
107- CSS='<style>body{font-family:Arial,Helvetica,sans-serif} ... </style>'
112+ # Styles: grid layout + "full-height" painted sidebar column
113+ CSS='<style>
114+ html, body { width:100%; max-width:none; margin:0; padding:0; font-family: Arial, Helvetica, sans-serif; color:#222; }
115+ h1, h2, h3, h4, h5, h6 { font-family: Arial, Helvetica, sans-serif; }
116+ pre code { display:block; padding:.75em; background:#f6f8fa; border-radius:6px; font-size:90%; overflow:auto; }
117+ code { font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; }
118+
119+ /* Page uses CSS Grid; paint the left column so the sidebar appears full-height */
120+ .page {
121+ display: grid;
122+ grid-template-columns: 220px 1fr;
123+ min-height: 100vh;
124+ background: linear-gradient(to right, #f4f4f4 0, #f4f4f4 220px, transparent 220px);
125+ }
126+
127+ .sidebar {
128+ padding: 20px;
129+ position: sticky;
130+ top: 0;
131+ height: 100vh; /* sidebar content scrolls independently if long */
132+ overflow: auto;
133+ }
134+ .sidebar a { display:block; margin-bottom:10px; color:#0366d6; text-decoration:none; font-weight:600; }
135+ .sidebar a:hover { text-decoration:underline; }
136+
137+ .content { width: 100%; }
138+ .container { width:100%; max-width: 1400px; margin: 0 auto; padding: 48px; }
139+
140+ /* Extras block spacing */
141+ .extras { margin-top: 48px; }
142+ .extras h2, .extras h3 { margin-top: 1.2em; }
143+
144+ @media (max-width: 1000px) {
145+ .page { display:block; background:none; }
146+ .sidebar { position: static; height:auto; overflow:visible; padding:16px; background:#f4f4f4; }
147+ .container { max-width:100%; margin:0; padding:24px; }
148+ }
149+ </style>'
150+
151+ # Inject CSS into <head> (or wrap if missing)
108152 if grep -qi '</head>' index.html; then
109153 awk -v css="$CSS" 'BEGIN{IGNORECASE=1} { if (!done && match(tolower($0), /<\/head>/)) { sub(/<\/head>/, css"</head>"); done=1 } print }' index.html > index.html.tmp
110154 mv index.html.tmp index.html
155+ else
156+ TMP=$(mktemp)
157+ printf '%s\n' '<!doctype html><html><head><meta charset="utf-8">' "$CSS" '</head><body>' > "$TMP"
158+ # Keep body content (if any) after opening <body>
159+ sed '1,/<body[^>]*>/d' index.html >> "$TMP" || true
160+ printf '%s\n' '</body></html>' >> "$TMP"
161+ mv "$TMP" index.html
111162 fi
112163
164+ # === Use dynamic Pages URL for the sidebar "Home" link ===
113165 HOMELINK="$PAGES_URL"
114- if ! grep -qi '<div class="page"' index.html; then
166+
167+ # Wrap body with grid + sidebar + content container (idempotent)
168+ if grep -qi '<div class="page"' index.html; then
169+ echo "Wrapper already present; skipping."
170+ else
115171 awk -v home="$HOMELINK" 'BEGIN{IGNORECASE=1}
116172 {
117173 if (!done && match(tolower($0), /<body[^>]*>/)) {
@@ -120,13 +176,22 @@ jobs:
120176 }
121177 print
122178 }' index.html > index.html.tmp && mv index.html.tmp index.html
179+
180+ # Close container/main/page before </body>
123181 awk 'BEGIN{IGNORECASE=1} { sub(/<\/body>/, "</div></main></div></body>"); print }' index.html > index.html.tmp && mv index.html.tmp index.html
124182 fi
125183
184+ # === Replace placeholders anywhere in the page ===
126185 esc() { printf '%s' "$1" | sed 's/[&/\\]/\\&/g'; }
127186 REPO_URL_ESC=$(esc "$REPO_URL")
128187 PAGES_URL_ESC=$(esc "$PAGES_URL")
129- sed -i -e "s/GITHUB_REPO_URL/${REPO_URL_ESC}/g" -e "s/GITHUB_REPO/${REPO_URL_ESC}/g" -e "s/GITHUB_PAGES_URL/${PAGES_URL_ESC}/g" index.html
188+
189+ sed -i \
190+ -e "s/GITHUB_REPO_URL/${REPO_URL_ESC}/g" \
191+ -e "s/GITHUB_REPO/${REPO_URL_ESC}/g" \
192+ -e "s/GITHUB_PAGES_URL/${PAGES_URL_ESC}/g" \
193+ index.html
194+
130195 echo "generated=$GENERATED" >> "$GITHUB_OUTPUT"
131196
132197 - name : Inject License/Citation/BibTeX block BELOW README content (inside container)
@@ -136,6 +201,7 @@ jobs:
136201 OWNER : ${{ github.repository_owner }}
137202 run : |
138203 set -e
204+
139205 REPO_NAME="${REPO#*/}"
140206 REPO_URL="https://github.com/$REPO"
141207 if [ "$REPO_NAME" = "${OWNER}.github.io" ]; then
@@ -146,8 +212,32 @@ jobs:
146212 LAST_UPDATE=$(git log -1 --format=%cI || date -u +%Y-%m-%dT%H:%M:%SZ)
147213 YEAR=$(date -u -d "$LAST_UPDATE" +%Y 2>/dev/null || date -u +%Y)
148214
149- citation_written="Steph Buongiorno. $REPO_NAME. $YEAR. Available at: $REPO_URL"
215+ # Gather human contributors (optional enhancement)
216+ logins=$(curl -s -H "Authorization: Bearer $GH_TOKEN" \
217+ "https://api.github.com/repos/$REPO/contributors?per_page=100&anon=false" \
218+ | jq -r '.[] | select((.type // "") != "Bot") | select(.login != "ghost") | .login' | sort -fu)
219+
220+ names=""
221+ for u in $logins; do
222+ name=$(curl -s -H "Authorization: Bearer $GH_TOKEN" "https://api.github.com/users/$u" | jq -r '.name // empty')
223+ [ -z "$name" ] && name="$u"
224+ if [ "$name" != "Steph Buongiorno" ] && [ "$u" != "stephbuon" ]; then
225+ names="$names\n$name"
226+ fi
227+ done
228+ names_sorted=$(printf "%b" "$names" | awk 'NF' | sort -fu)
229+
230+ citation_written="Steph Buongiorno"
231+ if [ -n "$names_sorted" ]; then
232+ citation_written="$citation_written; $(echo "$names_sorted" | paste -sd ', ' -)"
233+ fi
234+ citation_written="$citation_written. $REPO_NAME. $YEAR. Available at: $REPO_URL"
235+
150236 authors_bibtex="Steph Buongiorno"
237+ if [ -n "$names_sorted" ]; then
238+ authors_bibtex="$authors_bibtex and $(echo "$names_sorted" | paste -sd ' and ' -)"
239+ fi
240+
151241 bibtex="@misc{$REPO_NAME-$YEAR,
152242 author = {$authors_bibtex},
153243 title = {$REPO_NAME},
@@ -156,15 +246,19 @@ jobs:
156246 note = {Last updated: $LAST_UPDATE}
157247 }"
158248
249+ # Build the extras HTML block (includes both URLs)
159250 EXTRAS=$(cat <<HTML
160251 <section class="extras">
161252 <hr>
162253 <h2>License</h2>
163254 <p>This project is licensed under the <a href="LICENSE">MIT License</a>.</p>
255+
164256 <h2>Suggested Citation</h2>
165257 <p>$citation_written</p>
258+
166259 <h3>BibTeX</h3>
167260 <pre><code>$bibtex</code></pre>
261+
168262 <h3>Repository</h3>
169263 <p><em>$REPO_NAME</em><br>
170264 <a href="$REPO_URL">$REPO_URL</a><br>
@@ -174,6 +268,7 @@ jobs:
174268 HTML
175269 )
176270
271+ # Inject JUST BEFORE the wrapper closes: </div></main></div></body>
177272 awk -v block="$EXTRAS" 'BEGIN{IGNORECASE=1}
178273 {
179274 line=$0
0 commit comments