Skip to content

Commit f120ace

Browse files
committed
format update
1 parent 1985ec0 commit f120ace

1 file changed

Lines changed: 155 additions & 67 deletions

File tree

.github/workflows/pages.yml

Lines changed: 155 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ jobs:
7676
description: "${DESC}"
7777
permalink: pretty
7878
baseurl: "${BASE_URL}"
79+
github_repo: "https://github.com/${REPO_FULL}"
7980
8081
defaults:
8182
- scope:
@@ -97,45 +98,68 @@ jobs:
9798
<link rel="preconnect" href="https://fonts.googleapis.com">
9899
<link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@400;500&family=IBM+Plex+Mono:wght@400;500&display=swap" rel="stylesheet">
99100
<style>
101+
:root{
102+
--bg-page:#f6f8fa;--bg-content:#fff;--bg-header:#fff;--bg-code:#f6f8fa;
103+
--text-primary:#24292f;--text-secondary:#57606a;--text-muted:#8b949e;
104+
--border:#d0d7de;--link:#0969da;--accent:#fd8c73;
105+
--badge-bg:#dafbe1;--badge-text:#1a7f37;
106+
}
107+
@media(prefers-color-scheme:dark){
108+
:root{
109+
--bg-page:#0d1117;--bg-content:#161b22;--bg-header:#161b22;--bg-code:#1c2129;
110+
--text-primary:#e6edf3;--text-secondary:#8b949e;--text-muted:#6e7681;
111+
--border:#30363d;--link:#58a6ff;--accent:#f78166;
112+
--badge-bg:#1b3826;--badge-text:#3fb950;
113+
}
114+
}
100115
*{margin:0;padding:0;box-sizing:border-box}
101-
body{font-family:'IBM Plex Sans',-apple-system,sans-serif;color:#24292f;background:#f6f8fa;line-height:1.7}
102-
a{color:#0969da;text-decoration:none}
116+
body{font-family:'IBM Plex Sans',-apple-system,sans-serif;color:var(--text-primary);background:var(--bg-page);line-height:1.7}
117+
a{color:var(--link);text-decoration:none}
103118
a:hover{text-decoration:underline}
104-
.site-header{background:#fff;border-bottom:1px solid #d0d7de;padding:16px 24px;display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:12px}
105-
.site-title{font-family:'IBM Plex Mono',monospace;font-size:16px;font-weight:500;color:#24292f;text-decoration:none}
119+
.site-header{background:var(--bg-header);border-bottom:1px solid var(--border);padding:16px 24px;display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:12px}
120+
.site-title{font-size:16px;font-weight:500;color:var(--text-primary);text-decoration:none}
106121
.site-nav{display:flex;gap:20px;flex-wrap:wrap}
107-
.site-nav a{font-size:14px;color:#57606a;text-decoration:none;padding:4px 0}
108-
.site-nav a:hover{color:#24292f}
109-
.site-nav a.active{color:#24292f;font-weight:500;border-bottom:2px solid #fd8c73}
122+
.site-nav a{font-size:14px;color:var(--text-secondary);text-decoration:none;padding:4px 0}
123+
.site-nav a:hover{color:var(--text-primary)}
124+
.site-nav a.active{color:var(--text-primary);font-weight:500;border-bottom:2px solid var(--accent)}
110125
.container{max-width:820px;margin:32px auto;padding:0 24px}
111-
.content{background:#fff;border:1px solid #d0d7de;border-radius:6px;padding:32px}
112-
.content h1{font-size:24px;font-weight:500;margin:0 0 16px;border-bottom:1px solid #d0d7de;padding-bottom:8px}
113-
.content h2{font-size:20px;font-weight:500;margin:24px 0 12px;border-bottom:1px solid #d0d7de;padding-bottom:6px}
126+
.content{background:var(--bg-content);border:1px solid var(--border);border-radius:6px;padding:32px}
127+
.content h1{font-size:24px;font-weight:500;margin:0 0 16px;border-bottom:1px solid var(--border);padding-bottom:8px}
128+
.content h2{font-size:20px;font-weight:500;margin:24px 0 12px;border-bottom:1px solid var(--border);padding-bottom:6px}
114129
.content h3{font-size:16px;font-weight:500;margin:20px 0 8px}
115130
.content h4{font-size:14px;font-weight:500;margin:16px 0 6px}
116-
.content p{font-size:14px;color:#57606a;margin:0 0 16px}
117-
.content ul,.content ol{font-size:14px;color:#57606a;margin:0 0 16px;padding-left:24px}
131+
.content p{font-size:14px;color:var(--text-secondary);margin:0 0 16px}
132+
.content ul,.content ol{font-size:14px;color:var(--text-secondary);margin:0 0 16px;padding-left:24px}
118133
.content li{margin-bottom:4px}
119-
.content code{font-family:'IBM Plex Mono',monospace;font-size:13px;background:#f6f8fa;padding:2px 6px;border-radius:4px}
120-
.content pre{background:#f6f8fa;border:1px solid #d0d7de;border-radius:6px;padding:16px;overflow-x:auto;margin:8px 0 16px;line-height:1.5}
134+
.content code{font-family:'IBM Plex Mono',monospace;font-size:13px;background:var(--bg-code);padding:2px 6px;border-radius:4px}
135+
.content pre{background:var(--bg-code);border:1px solid var(--border);border-radius:6px;padding:16px;overflow-x:auto;margin:8px 0 16px;line-height:1.5}
121136
.content pre code{background:transparent;padding:0}
122137
.content table{width:100%;border-collapse:collapse;margin:8px 0 16px;font-size:14px}
123-
.content th,.content td{border:1px solid #d0d7de;padding:8px 12px;text-align:left}
124-
.content th{background:#f6f8fa;font-weight:500}
138+
.content th,.content td{border:1px solid var(--border);padding:8px 12px;text-align:left}
139+
.content th{background:var(--bg-code);font-weight:500}
125140
.content img{max-width:100%}
126-
#releases-container .release{border-bottom:1px solid #d0d7de;padding:20px 0}
127-
#releases-container .release:last-child{border-bottom:none}
128-
.release-tag{font-family:'IBM Plex Mono',monospace;font-size:16px;font-weight:500;color:#0969da}
129-
.release-date{font-size:13px;color:#8b949e;margin-left:8px}
130-
.release-latest{font-size:11px;padding:2px 8px;border-radius:16px;background:#dafbe1;color:#1a7f37;font-weight:500;margin-left:8px}
131-
.release-body{font-size:14px;color:#57606a;margin-top:8px;line-height:1.7}
132-
.release-body h2,.release-body h3{font-size:14px;font-weight:500;color:#24292f;margin:12px 0 4px;border:none;padding:0}
141+
.content strong{color:var(--text-primary)}
142+
.release{border:1px solid var(--border);border-radius:6px;margin-bottom:8px}
143+
.release summary{padding:12px 16px;cursor:pointer;display:flex;align-items:center;gap:8px;font-size:14px;list-style:none}
144+
.release summary::-webkit-details-marker{display:none}
145+
.release summary::before{content:'';display:inline-block;width:0;height:0;border-left:5px solid var(--text-muted);border-top:4px solid transparent;border-bottom:4px solid transparent;transition:transform 0.15s}
146+
.release[open] summary::before{transform:rotate(90deg)}
147+
.release-tag{font-family:'IBM Plex Mono',monospace;font-weight:500;color:var(--link)}
148+
.release-date{font-size:13px;color:var(--text-muted)}
149+
.release-latest{font-size:11px;padding:2px 8px;border-radius:16px;background:var(--badge-bg);color:var(--badge-text);font-weight:500}
150+
.release-body{padding:0 16px 16px;font-size:14px;color:var(--text-secondary);line-height:1.7}
151+
.release-body h2,.release-body h3{font-size:14px;font-weight:500;color:var(--text-primary);margin:12px 0 4px;border:none;padding:0}
133152
.release-body ul{padding-left:20px}
134153
.release-body li{margin-bottom:2px;font-size:13px}
135-
.release-assets{margin-top:12px}
136-
.release-assets summary{font-size:13px;font-weight:500;cursor:pointer;color:#24292f}
137-
.release-asset{font-family:'IBM Plex Mono',monospace;font-size:12px;color:#57606a;padding:3px 0}
138-
.loading{text-align:center;padding:32px;color:#8b949e;font-size:14px}
154+
.release-body pre{background:var(--bg-code);border:1px solid var(--border);border-radius:6px;padding:12px;overflow-x:auto;font-size:13px;line-height:1.5}
155+
.release-body code{font-family:'IBM Plex Mono',monospace;font-size:13px;background:var(--bg-code);padding:2px 4px;border-radius:3px}
156+
.release-body pre code{background:transparent;padding:0}
157+
.release-assets{margin-top:12px;border-top:1px solid var(--border);padding-top:12px}
158+
.release-assets summary{padding:0;font-size:13px;font-weight:500;cursor:pointer;color:var(--text-primary);list-style:revert}
159+
.release-assets summary::-webkit-details-marker{display:revert}
160+
.release-assets summary::before{display:none}
161+
.release-asset{font-family:'IBM Plex Mono',monospace;font-size:12px;color:var(--text-secondary);padding:3px 0}
162+
.loading{text-align:center;padding:32px;color:var(--text-muted);font-size:14px}
139163
@media(max-width:640px){.site-header{padding:12px 16px}.container{padding:0 12px;margin:16px auto}.content{padding:20px}}
140164
</style>
141165
</head>
@@ -150,6 +174,7 @@ jobs:
150174
{% for p in site.pages %}{% if p.path == 'LICENSE.md' %}<a href="{{ '/license/' | relative_url }}" {% if page.url contains '/license' %}class="active"{% endif %}>License</a>{% break %}{% endif %}{% endfor %}
151175
{% for p in site.pages %}{% if p.path == 'CONTRIBUTING.md' %}<a href="{{ '/contributing/' | relative_url }}" {% if page.url contains '/contributing' %}class="active"{% endif %}>Contributing</a>{% break %}{% endif %}{% endfor %}
152176
{% for p in site.pages %}{% if p.path == 'CODE_OF_CONDUCT.md' %}<a href="{{ '/code-of-conduct/' | relative_url }}" {% if page.url contains '/code-of-conduct' %}class="active"{% endif %}>Code of conduct</a>{% break %}{% endif %}{% endfor %}
177+
<a href="{{ site.github_repo }}" target="_blank" rel="noopener">View source</a>
153178
</nav>
154179
</header>
155180
<main class="container">
@@ -171,6 +196,18 @@ jobs:
171196
echo "Processed README.md → homepage"
172197
fi
173198
199+
# ── Fix relative links for Jekyll ─────────────────────────────
200+
# Jekyll with permalink:pretty changes paths, so relative links
201+
# like [X](CONTRIBUTING.md) or [X](LICENSE) would 404.
202+
# Point them at their Jekyll permalinks instead.
203+
# Only targets known community files in root-level markdown.
204+
for f in *.md; do
205+
[ -f "$f" ] || continue
206+
[ -f "CONTRIBUTING.md" ] && sed -i 's|\](CONTRIBUTING\.md)|\](contributing/)|g' "$f"
207+
[ -f "CODE_OF_CONDUCT.md" ] && sed -i 's|\](CODE_OF_CONDUCT\.md)|\](code-of-conduct/)|g' "$f"
208+
([ -f "LICENSE" ] || [ -f "LICENSE.txt" ] || [ -f "LICENSE.md" ]) && sed -i 's|\](LICENSE)|\](license/)|g' "$f"
209+
done
210+
174211
# ── Docs: add front matter + create index ─────────────────────
175212
if [ -d "docs" ]; then
176213
for f in docs/*.md; do
@@ -213,65 +250,116 @@ jobs:
213250
fi
214251
215252
# ── Releases page ─────────────────────────────────────────────
253+
# Write the JS to a separate file to avoid heredoc escaping issues
254+
mkdir -p _includes
255+
cat > _includes/releases.js << 'JSEOF'
256+
(async function() {
257+
var c = document.getElementById('releases-container');
258+
var repo = c.getAttribute('data-repo');
259+
try {
260+
var res = await fetch('https://api.github.com/repos/' + repo + '/releases');
261+
if (!res.ok) throw new Error(res.status);
262+
var data = await res.json();
263+
if (!data.length) { c.innerHTML = '<p>No releases found.</p>'; return; }
264+
265+
function md(s) {
266+
if (!s) return '';
267+
var lines = s.split('\n');
268+
var html = '';
269+
var inList = false;
270+
for (var i = 0; i < lines.length; i++) {
271+
var line = lines[i];
272+
var h3 = line.match(/^### (.+)$/);
273+
var h2 = line.match(/^## (.+)$/);
274+
var li = line.match(/^\* (.+)$/);
275+
var cb = line.match(/^```/);
276+
if (cb) {
277+
if (inList) { html += '</ul>'; inList = false; }
278+
var code = '';
279+
i++;
280+
while (i < lines.length && !lines[i].match(/^```/)) { code += lines[i] + '\n'; i++; }
281+
html += '<pre><code>' + code + '</code></pre>';
282+
} else if (h2) {
283+
if (inList) { html += '</ul>'; inList = false; }
284+
html += '<h2>' + h2[1] + '</h2>';
285+
} else if (h3) {
286+
if (inList) { html += '</ul>'; inList = false; }
287+
html += '<h3>' + h3[1] + '</h3>';
288+
} else if (li) {
289+
if (!inList) { html += '<ul>'; inList = true; }
290+
var text = li[1].replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2">$1</a>');
291+
html += '<li>' + text + '</li>';
292+
} else {
293+
if (inList) { html += '</ul>'; inList = false; }
294+
if (line.trim() === '---') { html += '<hr>'; }
295+
else if (line.trim()) {
296+
var text = line.replace(/`([^`]+)`/g, '<code>$1</code>').replace(/\*\*([^*]+)\*\*/g, '<strong>$1</strong>').replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2">$1</a>');
297+
html += '<p>' + text + '</p>';
298+
}
299+
}
300+
}
301+
if (inList) html += '</ul>';
302+
return html;
303+
}
304+
305+
c.innerHTML = data.map(function(r, i) {
306+
var d = new Date(r.published_at).toLocaleDateString('en-GB', { day: 'numeric', month: 'short', year: 'numeric' });
307+
var latest = i === 0 ? '<span class="release-latest">latest</span>' : '';
308+
var openAttr = i === 0 ? ' open' : '';
309+
var assets = '';
310+
if (r.assets.length) {
311+
assets = '<details class="release-assets"><summary>Assets (' + r.assets.length + ')</summary>';
312+
for (var j = 0; j < r.assets.length; j++) {
313+
var a = r.assets[j];
314+
assets += '<div class="release-asset">' + a.name + ' <span style="color:var(--text-muted)">' + (a.size / 1024).toFixed(1) + ' KB</span></div>';
315+
}
316+
assets += '</details>';
317+
}
318+
return '<details class="release"' + openAttr + '><summary><span class="release-tag">' + r.tag_name + '</span>' + latest + '<span class="release-date">' + d + '</span></summary><div class="release-body">' + md(r.body) + assets + '</div></details>';
319+
}).join('');
320+
} catch(e) {
321+
c.innerHTML = '<p>Unable to load releases. Visit <a href="https://github.com/' + repo + '/releases">GitHub</a> directly.</p>';
322+
}
323+
})();
324+
JSEOF
325+
216326
cat > releases.md << RELEOF
217327
---
218328
layout: default
219329
title: Releases
220330
permalink: /releases/
221331
---
222332
# Releases
223-
<div id="releases-container"><div class="loading">Loading releases...</div></div>
333+
<div id="releases-container" data-repo="${REPO_FULL}"><div class="loading">Loading releases...</div></div>
224334
<script>
225-
(async function(){
226-
const c=document.getElementById('releases-container');
227-
try{
228-
const r=await fetch('https://api.github.com/repos/${REPO_FULL}/releases');
229-
if(!r.ok)throw new Error(r.status);
230-
const data=await r.json();
231-
if(!data.length){c.innerHTML='<p>No releases found.</p>';return}
232-
c.innerHTML=data.map((r,i)=>{
233-
const d=new Date(r.published_at).toLocaleDateString('en-GB',{day:'numeric',month:'short',year:'numeric'});
234-
const l=i===0?'<span class="release-latest">latest</span>':'';
235-
const a=r.assets.length?'<details class="release-assets"><summary>Assets ('+r.assets.length+')</summary>'+r.assets.map(a=>'<div class="release-asset">'+a.name+' <span style="color:#8b949e">'+(a.size/1024).toFixed(1)+' KB</span></div>').join('')+'</details>':'';
236-
let b=(r.body||'').replace(/^### (.+)$/gm,'<h3>$1</h3>').replace(/^## (.+)$/gm,'<h2>$1</h2>').replace(/^\* (.+)$/gm,'<li>$1</li>').replace(/(<li>.*<\/li>\n?)+/gs,'<ul>$&</ul>').replace(/\x60\x60\x60(\w*)\n([\s\S]*?)\x60\x60\x60/g,'<pre><code>$2</code></pre>').replace(/\x60([^\x60]+)\x60/g,'<code>$1</code>').replace(/\[([^\]]+)\]\(([^)]+)\)/g,'<a href="$2">$1</a>').replace(/\n\n/g,'<br><br>').replace(/\n/g,'<br>');
237-
return '<div class="release"><div><span class="release-tag">'+r.tag_name+'</span>'+l+'<span class="release-date">'+d+'</span></div><div class="release-body">'+b+'</div>'+a+'</div>';
238-
}).join('');
239-
}catch(e){
240-
c.innerHTML='<p>Unable to load releases. Visit <a href="https://github.com/${REPO_FULL}/releases">GitHub</a> directly.</p>';
241-
}
242-
})();
335+
{% include releases.js %}
243336
</script>
244337
RELEOF
245338
echo "Created releases.md"
246339
247-
# ── License page (from LICENSE/LICENSE.txt) ────────────────────
340+
# ── License page (full content from LICENSE/LICENSE.txt) ──────
248341
LICENSE_SRC=""
249342
for lf in LICENSE LICENSE.txt; do
250343
[ -f "$lf" ] && LICENSE_SRC="$lf" && break
251344
done
252345
253-
if [ -n "$LICENSE_SRC" ] || [ -f "LICENSE.md" ]; then
254-
SRC="${LICENSE_SRC:-LICENSE.md}"
255-
LICENSE_TYPE="License"
256-
grep -qi "apache" "$SRC" 2>/dev/null && LICENSE_TYPE="Apache License 2.0"
257-
grep -qi "mit license" "$SRC" 2>/dev/null && LICENSE_TYPE="MIT License"
258-
grep -qi "gnu general public" "$SRC" 2>/dev/null && LICENSE_TYPE="GPL"
259-
grep -qi "bsd" "$SRC" 2>/dev/null && LICENSE_TYPE="BSD License"
260-
346+
if [ -n "$LICENSE_SRC" ]; then
347+
# Create LICENSE.md with front matter + full license text
261348
if ! ([ -f "LICENSE.md" ] && head -1 LICENSE.md | grep -q '^\-\-\-'); then
262-
cat > LICENSE.md << LICEOF
263-
---
264-
layout: default
265-
title: License
266-
permalink: /license/
267-
---
268-
# License
269-
This project is licensed under the **${LICENSE_TYPE}**.
270-
271-
See the [LICENSE](https://github.com/${REPO_FULL}/blob/main/${SRC}) file for the full license text.
272-
LICEOF
273-
echo "Created LICENSE.md (${LICENSE_TYPE})"
349+
TEMP=$(mktemp)
350+
printf -- '---\nlayout: default\ntitle: License\npermalink: /license/\n---\n\n# License\n\n```\n' > "$TEMP"
351+
cat "$LICENSE_SRC" >> "$TEMP"
352+
printf '\n```\n' >> "$TEMP"
353+
mv "$TEMP" LICENSE.md
354+
echo "Created LICENSE.md from ${LICENSE_SRC}"
274355
fi
356+
elif [ -f "LICENSE.md" ] && ! head -1 LICENSE.md | grep -q '^\-\-\-'; then
357+
# LICENSE.md exists but has no front matter
358+
TEMP=$(mktemp)
359+
printf -- '---\nlayout: default\ntitle: License\npermalink: /license/\n---\n\n' > "$TEMP"
360+
cat LICENSE.md >> "$TEMP"
361+
mv "$TEMP" LICENSE.md
362+
echo "Processed LICENSE.md"
275363
fi
276364
277365
# ── CONTRIBUTING.md ───────────────────────────────────────────

0 commit comments

Comments
 (0)