Skip to content

Commit c83eebe

Browse files
Merge pull request #75 from Staninna/decoupled-css
Decoupled css part 2
2 parents 920617b + 852dc3b commit c83eebe

File tree

6 files changed

+4008
-1620
lines changed

6 files changed

+4008
-1620
lines changed

.github/workflows/cd.yml

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
name: Pages – aggregate all branches
2+
3+
on:
4+
push:
5+
branches: ["**"]
6+
workflow_dispatch:
7+
8+
permissions:
9+
contents: read
10+
pages: write
11+
id-token: write
12+
13+
concurrency:
14+
group: pages
15+
cancel-in-progress: true
16+
17+
jobs:
18+
aggregate_deploy:
19+
runs-on: ubuntu-latest
20+
environment:
21+
name: github-pages
22+
url: ${{ steps.deploy.outputs.page_url }}
23+
24+
steps:
25+
- name: Checkout (shallow)
26+
uses: actions/checkout@v4
27+
with:
28+
fetch-depth: 1
29+
30+
- name: Configure Pages
31+
uses: actions/configure-pages@v5
32+
33+
- name: Aggregate and build recursive directory pages
34+
shell: bash
35+
run: |
36+
set -euo pipefail
37+
38+
# jq for JSON escaping (present on runners, but ensure)
39+
if ! command -v jq >/dev/null 2>&1; then
40+
sudo apt-get update -y
41+
sudo apt-get install -y jq
42+
fi
43+
44+
REPO="${GITHUB_REPOSITORY#*/}"
45+
SITE_ROOT="/${REPO}/"
46+
47+
mkdir -p public
48+
: > public/.nojekyll
49+
50+
# Tiny favicon assets to avoid 404s
51+
printf "%s" \
52+
"<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'><text y='14' font-size='14'>🚀</text></svg>" \
53+
> public/favicon.svg
54+
55+
# List remote branches
56+
mapfile -t BRANCHES < <(
57+
git ls-remote --heads origin | awk '{print $2}' \
58+
| sed 's@refs/heads/@@'
59+
)
60+
61+
# Landing page (no globals except window.__branches)
62+
cat > public/index.html <<'HTML'
63+
<!doctype html>
64+
<meta charset="utf-8" />
65+
<meta name="viewport" content="width=device-width,initial-scale=1" />
66+
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Ctext y='14' font-size='14'%3E🚀%3C/text%3E%3C/svg%3E" />
67+
<title>Branches</title>
68+
<style>
69+
body{font-family:system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Arial;
70+
margin:24px;background:#0d1117;color:#e6edf3}
71+
a{color:#58a6ff;text-decoration:none}
72+
.card{background:#161b22;padding:16px;border-radius:8px;margin:12px 0}
73+
input{background:#0b0f14;border:1px solid #30363d;color:#e6edf3;
74+
padding:8px 10px;border-radius:6px;width:100%;max-width:420px}
75+
</style>
76+
<h1>Branches</h1>
77+
<input id="q" placeholder="Filter branches..." />
78+
<div id="list"></div>
79+
<script>window.__branches=window.__branches||[];</script>
80+
HTML
81+
82+
# Emit index.html for a directory
83+
gen_index_dir() {
84+
local DIR="$1" ROOT="$2" BR="$3"
85+
local rel="${DIR#$ROOT}"
86+
local title="Branch: ${BR}${rel:-/}"
87+
88+
{
89+
echo "<!doctype html><meta charset='utf-8'/>"
90+
echo "<meta name='viewport' content='width=device-width,initial-scale=1'/>"
91+
echo "<link rel='icon' href=\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Ctext y='14' font-size='14'%3E🚀%3C/text%3E%3C/svg%3E\" />"
92+
echo "<title>${title}</title>"
93+
echo "<style>body{font-family:system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Arial;margin:24px;background:#0d1117;color:#e6edf3}a{color:#58a6ff;text-decoration:none}table{width:100%;border-collapse:collapse}th,td{padding:8px;border-bottom:1px solid #30363d}tr:hover{background:#161b22}</style>"
94+
echo "<h1>${title}</h1>"
95+
if [[ "$DIR" != "$ROOT" ]]; then
96+
echo "<p><a href='../'>⬆ Up</a> • <a href='${SITE_ROOT}'>All branches</a></p>"
97+
else
98+
echo "<p><a href='${SITE_ROOT}'>All branches</a></p>"
99+
fi
100+
echo "<table><thead><tr><th>Name</th><th style='width:120px'>Size</th><th style='width:180px'>Modified</th></tr></thead><tbody>"
101+
102+
# Subdirectories
103+
while IFS= read -r d; do
104+
[[ -n "$d" ]] || continue
105+
printf "<tr><td>📁 <a href='./%s/'>%s/</a></td><td>—</td><td>—</td></tr>\n" "$d" "$d"
106+
done < <(find "$DIR" -mindepth 1 -maxdepth 1 -type d -printf '%f\n' | sort)
107+
108+
# Files
109+
while IFS= read -r f; do
110+
[[ -n "$f" ]] || continue
111+
size=$(stat -c %s "$DIR/$f" 2>/dev/null || echo 0)
112+
size_h=$(numfmt --to=iec --suffix=B "$size" 2>/dev/null || echo "$size")
113+
mod=$(date -r "$DIR/$f" "+%Y-%m-%d %H:%M" 2>/dev/null || echo "")
114+
printf "<tr><td>📄 <a href='./%s'>%s</a></td><td>%s</td><td>%s</td></tr>\n" "$f" "$f" "$size_h" "$mod"
115+
done < <(find "$DIR" -mindepth 1 -maxdepth 1 -type f ! -name 'index.html' -printf '%f\n' | sort)
116+
117+
echo "</tbody></table>"
118+
echo "<p style='opacity:.7'>Generated $(date -u '+%Y-%m-%d %H:%M UTC')</p>"
119+
} > "$DIR/index.html"
120+
}
121+
122+
# Build per-branch trees and indexes
123+
for BR in "${BRANCHES[@]}"; do
124+
SAFE="$(echo "$BR" | tr '/:@ ' '----' | sed 's/[^A-Za-z0-9._-]/-/g')"
125+
mkdir -p "public/$SAFE"
126+
127+
git fetch --depth=1 origin "$BR"
128+
git archive --format=tar FETCH_HEAD | tar -x -C "public/$SAFE"
129+
130+
# Keep only static assets; prune empty dirs
131+
rm -rf "public/$SAFE/.git" "public/$SAFE/.github" \
132+
"public/$SAFE/node_modules"
133+
find "public/$SAFE" -type f ! \
134+
\( -name '*.html' -o -name '*.js' -o -name '*.css' -o \
135+
-name '*.json' -o -name '*.png' -o -name '*.jpg' -o \
136+
-name '*.jpeg' -o -name '*.gif' -o -name '*.svg' \) \
137+
-delete
138+
find "public/$SAFE" -type d -empty -delete
139+
140+
ROOT_DIR="public/$SAFE"
141+
while IFS= read -r -d '' d; do
142+
gen_index_dir "$d" "$ROOT_DIR" "$BR"
143+
done < <(find "$ROOT_DIR" -type d -print0)
144+
145+
# Append to landing page (JSON-escaped)
146+
SAFE_JSON=$(printf '%s' "$SAFE" | jq -Rr @json)
147+
BR_JSON=$(printf '%s' "$BR" | jq -Rr @json)
148+
echo "<script>window.__branches.push({safe:$SAFE_JSON,name:$BR_JSON});</script>" \
149+
>> public/index.html
150+
done
151+
152+
# Finish landing page
153+
cat >> public/index.html <<'HTML'
154+
<script>
155+
(() => {
156+
const q = document.getElementById('q');
157+
const listEl = document.getElementById('list');
158+
159+
function render(filter = '') {
160+
listEl.innerHTML = '';
161+
const qv = filter.toLowerCase();
162+
for (const b of (window.__branches || []).filter(x =>
163+
x.name.toLowerCase().includes(qv)
164+
)) {
165+
const div = document.createElement('div');
166+
div.className = 'card';
167+
div.innerHTML = `<strong>${b.name}</strong><div>
168+
<a href="./${b.safe}/">Open</a>
169+
</div>`;
170+
listEl.appendChild(div);
171+
}
172+
}
173+
174+
q.addEventListener('input', (e) => render(e.target.value));
175+
render();
176+
})();
177+
</script>
178+
HTML
179+
180+
- name: Upload Pages artifact
181+
uses: actions/upload-pages-artifact@v4
182+
with:
183+
path: public
184+
185+
- name: Deploy to GitHub Pages
186+
id: deploy
187+
uses: actions/deploy-pages@v4

0 commit comments

Comments
 (0)