diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index e1cb940..2b82407 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -76,6 +76,7 @@ jobs: description: "${DESC}" permalink: pretty baseurl: "${BASE_URL}" + github_repo: "https://github.com/${REPO_FULL}" defaults: - scope: @@ -97,45 +98,68 @@ jobs: @@ -150,6 +174,7 @@ jobs: {% for p in site.pages %}{% if p.path == 'LICENSE.md' %}License{% break %}{% endif %}{% endfor %} {% for p in site.pages %}{% if p.path == 'CONTRIBUTING.md' %}Contributing{% break %}{% endif %}{% endfor %} {% for p in site.pages %}{% if p.path == 'CODE_OF_CONDUCT.md' %}Code of conduct{% break %}{% endif %}{% endfor %} + View source
@@ -171,6 +196,18 @@ jobs: echo "Processed README.md → homepage" fi + # ── Fix relative links for Jekyll ───────────────────────────── + # Jekyll with permalink:pretty changes paths, so relative links + # like [X](CONTRIBUTING.md) or [X](LICENSE) would 404. + # Point them at their Jekyll permalinks instead. + # Only targets known community files in root-level markdown. + for f in *.md; do + [ -f "$f" ] || continue + [ -f "CONTRIBUTING.md" ] && sed -i 's|\](CONTRIBUTING\.md)|\](contributing/)|g' "$f" + [ -f "CODE_OF_CONDUCT.md" ] && sed -i 's|\](CODE_OF_CONDUCT\.md)|\](code-of-conduct/)|g' "$f" + ([ -f "LICENSE" ] || [ -f "LICENSE.txt" ] || [ -f "LICENSE.md" ]) && sed -i 's|\](LICENSE)|\](license/)|g' "$f" + done + # ── Docs: add front matter + create index ───────────────────── if [ -d "docs" ]; then for f in docs/*.md; do @@ -213,6 +250,79 @@ jobs: fi # ── Releases page ───────────────────────────────────────────── + # Write the JS to a separate file to avoid heredoc escaping issues + mkdir -p _includes + cat > _includes/releases.js << 'JSEOF' + (async function() { + var c = document.getElementById('releases-container'); + var repo = c.getAttribute('data-repo'); + try { + var res = await fetch('https://api.github.com/repos/' + repo + '/releases'); + if (!res.ok) throw new Error(res.status); + var data = await res.json(); + if (!data.length) { c.innerHTML = '

No releases found.

'; return; } + + function md(s) { + if (!s) return ''; + var lines = s.split('\n'); + var html = ''; + var inList = false; + for (var i = 0; i < lines.length; i++) { + var line = lines[i]; + var h3 = line.match(/^### (.+)$/); + var h2 = line.match(/^## (.+)$/); + var li = line.match(/^\* (.+)$/); + var cb = line.match(/^```/); + if (cb) { + if (inList) { html += ''; inList = false; } + var code = ''; + i++; + while (i < lines.length && !lines[i].match(/^```/)) { code += lines[i] + '\n'; i++; } + html += '
' + code + '
'; + } else if (h2) { + if (inList) { html += ''; inList = false; } + html += '

' + h2[1] + '

'; + } else if (h3) { + if (inList) { html += ''; inList = false; } + html += '

' + h3[1] + '

'; + } else if (li) { + if (!inList) { html += ''; inList = false; } + if (line.trim() === '---') { html += '
'; } + else if (line.trim()) { + var text = line.replace(/`([^`]+)`/g, '$1').replace(/\*\*([^*]+)\*\*/g, '$1').replace(/\[([^\]]+)\]\(([^)]+)\)/g, '$1'); + html += '

' + text + '

'; + } + } + } + if (inList) html += ''; + return html; + } + + c.innerHTML = data.map(function(r, i) { + var d = new Date(r.published_at).toLocaleDateString('en-GB', { day: 'numeric', month: 'short', year: 'numeric' }); + var latest = i === 0 ? 'latest' : ''; + var openAttr = i === 0 ? ' open' : ''; + var assets = ''; + if (r.assets.length) { + assets = '
Assets (' + r.assets.length + ')'; + for (var j = 0; j < r.assets.length; j++) { + var a = r.assets[j]; + assets += '
' + a.name + ' ' + (a.size / 1024).toFixed(1) + ' KB
'; + } + assets += '
'; + } + return '
' + r.tag_name + '' + latest + '' + d + '
' + md(r.body) + assets + '
'; + }).join(''); + } catch(e) { + c.innerHTML = '

Unable to load releases. Visit GitHub directly.

'; + } + })(); + JSEOF + cat > releases.md << RELEOF --- layout: default @@ -220,58 +330,36 @@ jobs: permalink: /releases/ --- # Releases -
Loading releases...
+
Loading releases...
RELEOF echo "Created releases.md" - # ── License page (from LICENSE/LICENSE.txt) ──────────────────── + # ── License page (full content from LICENSE/LICENSE.txt) ────── LICENSE_SRC="" for lf in LICENSE LICENSE.txt; do [ -f "$lf" ] && LICENSE_SRC="$lf" && break done - if [ -n "$LICENSE_SRC" ] || [ -f "LICENSE.md" ]; then - SRC="${LICENSE_SRC:-LICENSE.md}" - LICENSE_TYPE="License" - grep -qi "apache" "$SRC" 2>/dev/null && LICENSE_TYPE="Apache License 2.0" - grep -qi "mit license" "$SRC" 2>/dev/null && LICENSE_TYPE="MIT License" - grep -qi "gnu general public" "$SRC" 2>/dev/null && LICENSE_TYPE="GPL" - grep -qi "bsd" "$SRC" 2>/dev/null && LICENSE_TYPE="BSD License" - + if [ -n "$LICENSE_SRC" ]; then + # Create LICENSE.md with front matter + full license text if ! ([ -f "LICENSE.md" ] && head -1 LICENSE.md | grep -q '^\-\-\-'); then - cat > LICENSE.md << LICEOF - --- - layout: default - title: License - permalink: /license/ - --- - # License - This project is licensed under the **${LICENSE_TYPE}**. - - See the [LICENSE](https://github.com/${REPO_FULL}/blob/main/${SRC}) file for the full license text. - LICEOF - echo "Created LICENSE.md (${LICENSE_TYPE})" + TEMP=$(mktemp) + printf -- '---\nlayout: default\ntitle: License\npermalink: /license/\n---\n\n# License\n\n```\n' > "$TEMP" + cat "$LICENSE_SRC" >> "$TEMP" + printf '\n```\n' >> "$TEMP" + mv "$TEMP" LICENSE.md + echo "Created LICENSE.md from ${LICENSE_SRC}" fi + elif [ -f "LICENSE.md" ] && ! head -1 LICENSE.md | grep -q '^\-\-\-'; then + # LICENSE.md exists but has no front matter + TEMP=$(mktemp) + printf -- '---\nlayout: default\ntitle: License\npermalink: /license/\n---\n\n' > "$TEMP" + cat LICENSE.md >> "$TEMP" + mv "$TEMP" LICENSE.md + echo "Processed LICENSE.md" fi # ── CONTRIBUTING.md ───────────────────────────────────────────