1- name : Deploy to GitHub Pages (force-write repo URL with debug)
1+ name : Deploy to GitHub Pages
22
33on :
44 push :
@@ -26,54 +26,163 @@ jobs:
2626 - name : Install tools
2727 run : |
2828 sudo apt-get update
29- sudo apt-get install -y pandoc jq
29+ sudo apt-get install -y pandoc jq curl
30+
31+ - id : ensure_license
32+ name : Ensure MIT License exists (and mark if created)
33+ run : |
34+ if [ ! -f LICENSE ]; then
35+ YEAR=$(date +%Y)
36+ printf '%s\n' "MIT License" "" "Copyright (c) $YEAR Steph Buongiorno" "" "Permission is hereby granted, free of charge, to any person obtaining a copy" "of this software and associated documentation files (the \"Software\"), to deal" "in the Software without restriction, including without limitation the rights" "to use, copy, modify, merge, publish, distribute, sublicense, and/or sell" "copies of the Software, and to permit persons to whom the Software is" "furnished to do so, subject to the following conditions:" "" "The above copyright notice and this permission notice shall be included in all" "copies or substantial portions of the Software." "" "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR" "IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY," "FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE" "AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER" "LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM," "OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE" "SOFTWARE." > LICENSE
37+ echo "MIT License generated."
38+ echo "created=true" >> "$GITHUB_OUTPUT"
39+ else
40+ echo "LICENSE file already exists — skipping generation."
41+ echo "created=false" >> "$GITHUB_OUTPUT"
42+ fi
43+
44+ - name : Commit LICENSE to repo (first time only)
45+ if : steps.ensure_license.outputs.created == 'true'
46+ env :
47+ GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
48+ run : |
49+ git config user.name "github-actions[bot]"
50+ git config user.email "github-actions[bot]@users.noreply.github.com"
51+ git add LICENSE
52+ git commit -m "Add MIT LICENSE (auto-generated)"
53+ git push
3054
3155 - id : build_page
32- name : Build index.html (keep existing, or README -> HTML)
56+ name : Build index.html with custom template + grid sidebar
3357 env :
3458 REPO_HTML_TITLE : ${{ github.repository }}
3559 run : |
36- set -euo pipefail
60+ set -e
61+ GENERATED=0
62+
63+ # Minimal Pandoc template (no default CSS)
64+ cat > pandoc_template.html <<'TPL'
65+ <!doctype html>
66+ <html>
67+ <head>
68+ <meta charset="utf-8">
69+ <meta name="viewport" content="width=device-width, initial-scale=1">
70+ <title>$title$</title>
71+ </head>
72+ <body>
73+ $for(include-before)$
74+ $include-before$
75+ $endfor$
76+ $body$
77+ $for(include-after)$
78+ $include-after$
79+ $endfor$
80+ </body>
81+ </html>
82+ TPL
83+
3784 if [ -f index.html ]; then
3885 echo "Keeping existing index.html (not regenerating)."
3986 elif [ -f README.md ]; then
87+ echo "Generating index.html from README.md..."
4088 pandoc README.md -f markdown -t html -s \
41- --highlight-style=tango \
89+ --template=pandoc_template.html \
4290 -o index.html \
4391 --metadata title="$REPO_HTML_TITLE"
92+ GENERATED=1
4493 else
94+ echo "No index.html or README.md found; writing minimal page."
4595 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
96+ GENERATED=1
4697 fi
4798
48- # Minimal CSS injection (escape </head> properly in awk regex)
49- CSS_BLOCK='<style>body{font-family:Arial,Helvetica,sans-serif} pre code{display:block;padding:.75em;background:#f6f8fa;border-radius:6px;font-size:90%;overflow:auto}</style>'
99+ HOMELINK="https://democracy-lab.github.io/"
100+
101+ # Styles: grid layout + "full-height" painted sidebar column
102+ CSS='<style>
103+ html, body { width:100%; max-width:none; margin:0; padding:0; font-family: Arial, Helvetica, sans-serif; color:#222; }
104+ h1, h2, h3, h4, h5, h6 { font-family: Arial, Helvetica, sans-serif; }
105+ pre code { display:block; padding:.75em; background:#f6f8fa; border-radius:6px; font-size:90%; overflow:auto; }
106+ code { font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; }
107+
108+ /* Page uses CSS Grid; paint the left column so the sidebar appears full-height */
109+ .page {
110+ display: grid;
111+ grid-template-columns: 220px 1fr;
112+ min-height: 100vh;
113+ background: linear-gradient(to right, #f4f4f4 0, #f4f4f4 220px, transparent 220px);
114+ }
115+
116+ .sidebar {
117+ padding: 20px;
118+ position: sticky;
119+ top: 0;
120+ height: 100vh; /* sidebar content scrolls independently if long */
121+ overflow: auto;
122+ }
123+ .sidebar a { display:block; margin-bottom:10px; color:#0366d6; text-decoration:none; font-weight:600; }
124+ .sidebar a:hover { text-decoration:underline; }
125+
126+ .content { width: 100%; }
127+ .container { width:100%; max-width: 1400px; margin: 0 auto; padding: 48px; }
128+
129+ /* Extras block spacing */
130+ .extras { margin-top: 48px; }
131+ .extras h2, .extras h3 { margin-top: 1.2em; }
132+
133+ @media (max-width: 1000px) {
134+ .page { display:block; background:none; }
135+ .sidebar { position: static; height:auto; overflow:visible; padding:16px; background:#f4f4f4; }
136+ .container { max-width:100%; margin:0; padding:24px; }
137+ }
138+ </style>'
139+
140+ # Inject CSS into <head> (or wrap if missing)
50141 if grep -qi '</head>' index.html; then
51- awk -v css="$CSS_BLOCK " 'BEGIN{IGNORECASE=1} { if (!done && match(tolower($0), /<\/head>/)) { sub(/<\/head>/, css"</head>"); done=1 } print }' index.html > index.html.tmp
142+ 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
52143 mv index.html.tmp index.html
53144 else
54145 TMP=$(mktemp)
55- printf '%s\n' '<!doctype html><html><head><meta charset="utf-8">' "${CSS_BLOCK} " '</head><body>' > "$TMP"
56- cat index.html >> "$TMP"
146+ printf '%s\n' '<!doctype html><html><head><meta charset="utf-8">' "$CSS " '</head><body>' > "$TMP"
147+ sed '1,/<body[^>]*>/d' index.html >> "$TMP" || true
57148 printf '%s\n' '</body></html>' >> "$TMP"
58149 mv "$TMP" index.html
59150 fi
60151
61- - name : Force-write License/Citation/BibTeX/Repository with URL + DEBUG
152+ # Wrap body with grid + sidebar + content container (idempotent)
153+ if grep -qi '<div class="page"' index.html; then
154+ echo "Wrapper already present; skipping."
155+ else
156+ awk -v home="$HOMELINK" 'BEGIN{IGNORECASE=1}
157+ {
158+ if (!done && match(tolower($0), /<body[^>]*>/)) {
159+ sub(/<body[^>]*>/, "&\n<div class=\"page\"><aside class=\"sidebar\"><a href=\"" home "\" aria-label=\"Go to home\">← Home</a></aside>\n<main class=\"content\"><div class=\"container\">");
160+ done=1
161+ }
162+ print
163+ }' index.html > index.html.tmp && mv index.html.tmp index.html
164+
165+ # Close container/main/page before </body>
166+ awk 'BEGIN{IGNORECASE=1} { sub(/<\/body>/, "</div></main></div></body>"); print }' index.html > index.html.tmp && mv index.html.tmp index.html
167+ fi
168+
169+ echo "generated=$GENERATED" >> "$GITHUB_OUTPUT"
170+
171+ - name : Inject License/Citation/BibTeX block BELOW README content (inside container)
172+ if : steps.build_page.outputs.generated == '1'
62173 env :
63174 GH_TOKEN : ${{ secrets.GITHUB_TOKEN }}
64175 REPO : ${{ github.repository }}
65- shell : bash
176+ OWNER : ${{ github.repository_owner }}
66177 run : |
67- set -Eeuo pipefail
178+ set -e
179+
68180 REPO_NAME="${REPO#*/}"
69181 REPO_URL="https://github.com/$REPO"
70182 LAST_UPDATE=$(git log -1 --format=%cI || date -u +%Y-%m-%dT%H:%M:%SZ)
71183 YEAR=$(date -u -d "$LAST_UPDATE" +%Y 2>/dev/null || date -u +%Y)
72184
73- echo "DEBUG: REPO=$REPO"
74- echo "DEBUG: REPO_URL=$REPO_URL"
75- echo "DEBUG: LAST_UPDATE=$LAST_UPDATE"
76-
185+ # Gather human contributors
77186 logins=$(curl -s -H "Authorization: Bearer $GH_TOKEN" \
78187 "https://api.github.com/repos/$REPO/contributors?per_page=100&anon=false" \
79188 | jq -r '.[] | select((.type // "") != "Bot") | select(.login != "ghost") | .login' | sort -fu)
82191 for u in $logins; do
83192 name=$(curl -s -H "Authorization: Bearer $GH_TOKEN" "https://api.github.com/users/$u" | jq -r '.name // empty')
84193 [ -z "$name" ] && name="$u"
85- names="$names\n$name"
194+ if [ "$name" != "Steph Buongiorno" ] && [ "$u" != "stephbuon" ]; then
195+ names="$names\n$name"
196+ fi
86197 done
87198 names_sorted=$(printf "%b" "$names" | awk 'NF' | sort -fu)
88199
@@ -98,38 +209,50 @@ jobs:
98209 fi
99210
100211 bibtex="@misc{$REPO_NAME-$YEAR,
101- author = {$authors_bibtex},
102- title = {$REPO_NAME},
103- year = {$YEAR},
104- howpublished = {\\url{$REPO_URL}},
105- note = {Last updated: $LAST_UPDATE}
212+ author = {$authors_bibtex},
213+ title = {$REPO_NAME},
214+ year = {$YEAR},
215+ howpublished = {\\url{$REPO_URL}},
216+ note = {Last updated: $LAST_UPDATE}
106217 }"
107218
108- # Remove any previous block entirely and append a fresh one
109- awk 'BEGIN{p=1} /<!-- BEGIN-REPO-META -->/{p=0} /<!-- END-REPO-META -->/{next} p{print}' index.html > index.clean.html || true
110- mv index.clean.html index.html || true
219+ # Build the extras HTML block
220+ EXTRAS=$(cat <<'HTML'
221+ <section class="extras">
222+ <hr>
223+ <h2>License</h2>
224+ <p>This project is licensed under the <a href="LICENSE">MIT License</a>.</p>
111225
112- cat >> index.html <<HTMLBLOCK
113- <!-- BEGIN-REPO-META -->
114- <hr>
115- <h2>License</h2>
116- <p>This project is licensed under the <a href="LICENSE">MIT License</a>.</p>
226+ <h2>Suggested Citation</h2>
227+ <p>__CITATION_WRITTEN__</p>
117228
118- <h2>Suggested Citation</h2 >
119- <p>$citation_written</p >
229+ <h3>BibTeX</h3 >
230+ <pre><code>__BIBTEX__</code></pre >
120231
121- <h3>BibTeX</h3>
122- <pre><code>$bibtex</code></pre>
232+ <h3>Repository</h3>
233+ <p><em>__REPO_NAME__</em><br>
234+ <a href="__REPO_URL__">__REPO_URL__</a><br>
235+ <strong>Last updated:</strong> __LAST_UPDATE__</p>
236+ </section>
237+ HTML
238+ )
123239
124- <h3>Repository</h3>
125- <p><em>$REPO_NAME</em><br>
126- <a href="$REPO_URL">$REPO_URL</a><br>
127- <strong>Last updated:</strong> $LAST_UPDATE</p>
128- <!-- END-REPO-META -->
129- HTMLBLOCK
240+ EXTRAS=${EXTRAS/__CITATION_WRITTEN__/$citation_written}
241+ EXTRAS=${EXTRAS/__BIBTEX__/$(printf "%s" "$bibtex" | sed 's/[&/\]/\\&/g')}
242+ EXTRAS=${EXTRAS/__REPO_NAME__/$REPO_NAME}
243+ EXTRAS=${EXTRAS/__REPO_URL__/$REPO_URL}
244+ EXTRAS=${EXTRAS/__LAST_UPDATE__/$LAST_UPDATE}
130245
131- echo "---------- FINAL LINES OF index.html ----------"
132- tail -n 60 index.html
246+ # Inject JUST BEFORE the wrapper closes: </div></main></div></body>
247+ awk -v block="$EXTRAS" 'BEGIN{IGNORECASE=1}
248+ {
249+ line=$0
250+ if (!done && match(tolower(line), /<\/div>\s*<\/main>\s*<\/div>\s*<\/body>/)) {
251+ sub(/<\/div>\s*<\/main>\s*<\/div>\s*<\/body>/, block"</div></main></div></body>")
252+ done=1
253+ }
254+ print
255+ }' index.html > index.html.tmp && mv index.html.tmp index.html
133256
134257 - name : Upload site artifact
135258 uses : actions/upload-pages-artifact@v3
0 commit comments