|
230 | 230 | fileMeta.textContent = ''; |
231 | 231 | fileContent.innerHTML = '<div class="small">Loading posts... please wait.</div>'; |
232 | 232 | try { |
233 | | - const baseUrl = `https://api.github.com/repos/${owner}/${repo}/contents`; |
| 233 | + const repoApi = `https://api.github.com/repos/${owner}/${repo}`; |
| 234 | + const baseUrl = `${repoApi}/contents`; |
234 | 235 | const postsUrl = `${baseUrl}/${encodeURIComponent(postsPath)}`; |
235 | 236 | const posts = await apiFetch(postsUrl); |
236 | 237 | if (!Array.isArray(posts)) { |
|
239 | 240 | return; |
240 | 241 | } |
241 | 242 |
|
242 | | - const dirs = posts.filter(p => p.type === 'dir'); |
| 243 | + // find directories under posts |
| 244 | + let dirs = posts.filter(p => p.type === 'dir'); |
| 245 | + // fetch latest commit for each directory so we can sort newest → oldest |
| 246 | + try { |
| 247 | + const dated = await Promise.all(dirs.map(async (d) => { |
| 248 | + try { |
| 249 | + const commits = await apiFetch(`${repoApi}/commits?path=${encodeURIComponent(postsPath + '/' + d.name)}&per_page=1`); |
| 250 | + const latest = Array.isArray(commits) && commits[0] && commits[0].commit ? (commits[0].commit.author?.date || commits[0].commit.committer?.date) : null; |
| 251 | + return {...d, _latestCommitDate: latest ? new Date(latest).toISOString() : null}; |
| 252 | + } catch (e) { |
| 253 | + return {...d, _latestCommitDate: null}; |
| 254 | + } |
| 255 | + })); |
| 256 | + // sort by latest commit date descending (newest first); fallback to name |
| 257 | + dated.sort((a,b) => { |
| 258 | + if (a._latestCommitDate && b._latestCommitDate) return b._latestCommitDate.localeCompare(a._latestCommitDate); |
| 259 | + if (a._latestCommitDate) return -1; |
| 260 | + if (b._latestCommitDate) return 1; |
| 261 | + return a.name.localeCompare(b.name); |
| 262 | + }); |
| 263 | + dirs = dated; |
| 264 | + } catch (e) { |
| 265 | + // if commit lookups fail, continue with unsorted dirs |
| 266 | + } |
243 | 267 | if (dirs.length === 0) { |
244 | 268 | setStatus('No post directories found under `posts`.', true); |
245 | 269 | fileContent.innerHTML = '<div class="small">No post directories found under `posts`.</div>'; |
|
264 | 288 | section.style.padding = '10px'; |
265 | 289 | section.style.borderRadius = '6px'; |
266 | 290 |
|
267 | | - const h = document.createElement('div'); |
268 | | - h.style.fontWeight = '700'; |
269 | | - h.style.marginBottom = '6px'; |
270 | | - h.textContent = dir.name; |
271 | | - section.appendChild(h); |
| 291 | + const header = document.createElement('div'); |
| 292 | + header.style.display = 'flex'; |
| 293 | + header.style.justifyContent = 'space-between'; |
| 294 | + header.style.alignItems = 'center'; |
| 295 | + header.style.marginBottom = '6px'; |
| 296 | + |
| 297 | + const titleDiv = document.createElement('div'); |
| 298 | + titleDiv.style.fontWeight = '700'; |
| 299 | + titleDiv.textContent = dir.name; |
| 300 | + |
| 301 | + const badge = document.createElement('div'); |
| 302 | + badge.className = 'small'; |
| 303 | + badge.style.opacity = '0.9'; |
| 304 | + badge.style.background = 'rgba(255,255,255,0.02)'; |
| 305 | + badge.style.padding = '4px 8px'; |
| 306 | + badge.style.borderRadius = '999px'; |
| 307 | + badge.style.fontSize = '12px'; |
| 308 | + badge.style.color = 'var(--muted)'; |
| 309 | + if (dir._latestCommitDate) { |
| 310 | + const d = new Date(dir._latestCommitDate); |
| 311 | + badge.textContent = d.toLocaleDateString(undefined, {year: 'numeric', month: 'short', day: 'numeric'}); |
| 312 | + badge.title = d.toISOString(); |
| 313 | + } else { |
| 314 | + badge.textContent = ''; |
| 315 | + } |
| 316 | + |
| 317 | + header.appendChild(titleDiv); |
| 318 | + header.appendChild(badge); |
| 319 | + section.appendChild(header); |
272 | 320 |
|
273 | 321 | if (!readmeFile) { |
274 | 322 | const note = document.createElement('div'); |
|
0 commit comments