84 lines
3.4 KiB
Plaintext
84 lines
3.4 KiB
Plaintext
---
|
|
import { getCollection } from 'astro:content';
|
|
import Base from '../../layouts/Base.astro';
|
|
import NewsCard from '../../components/NewsCard.astro';
|
|
import { PAGE_FIRST as FIRST, PAGE_REST as REST } from '../../lib/news.js';
|
|
|
|
// Paginated archive; the [...page] rest route makes page 1 the bare /news URL,
|
|
// then /news/2 … /news/N. Custom slicing instead of paginate(): page 1 holds
|
|
// FIRST items (1 featured lead + 24 grid = even 3-column rows), later pages
|
|
// REST — paginate() cannot vary page size. Chunk sizes live in lib/news.js,
|
|
// shared with sitemap.xml.js.
|
|
export async function getStaticPaths() {
|
|
const posts = (await getCollection('news', ({ data }) => !data.draft)).sort(
|
|
(a, b) => b.data.date.valueOf() - a.data.date.valueOf(),
|
|
);
|
|
const chunks = [posts.slice(0, FIRST)];
|
|
for (let i = FIRST; i < posts.length; i += REST) chunks.push(posts.slice(i, i + REST));
|
|
const lastPage = chunks.length;
|
|
const hrefOf = (n: number) => (n === 1 ? '/news' : `/news/${n}`);
|
|
return chunks.map((data, i) => {
|
|
const n = i + 1;
|
|
return {
|
|
params: { page: n === 1 ? undefined : String(n) },
|
|
props: { page: {
|
|
data,
|
|
currentPage: n,
|
|
lastPage,
|
|
url: {
|
|
prev: n > 1 ? hrefOf(n - 1) : undefined,
|
|
next: n < lastPage ? hrefOf(n + 1) : undefined,
|
|
},
|
|
} },
|
|
};
|
|
});
|
|
}
|
|
|
|
const { page } = Astro.props;
|
|
const first = page.currentPage === 1;
|
|
// Windowed page list — 1 … n-1 n n+1 … last (0 marks an ellipsis)
|
|
const nums = [];
|
|
for (let n = 1; n <= page.lastPage; n++) {
|
|
if (n === 1 || n === page.lastPage || Math.abs(n - page.currentPage) <= 1) nums.push(n);
|
|
else if (nums.at(-1) !== 0) nums.push(0);
|
|
}
|
|
const hrefFor = (n: number) => (n === 1 ? '/news' : `/news/${n}`);
|
|
---
|
|
<Base
|
|
title={first ? 'CTAO Science Portal - News' : `CTAO Science Portal - News, page ${page.currentPage}`}
|
|
description={first ? 'News and announcements of the CTAO' : `News and announcements of the CTAO, page ${page.currentPage} of ${page.lastPage}`}
|
|
>
|
|
{/* Section-landing archetype: white head, display Galaxy h1 + standfirst
|
|
(the navy band is reserved for / and /login). */}
|
|
<header class="container page-head">
|
|
<h1>News & Announcements</h1>
|
|
<p class="standfirst">Science highlights and updates from the observatory and its partners.</p>
|
|
</header>
|
|
|
|
<section class="container page">
|
|
<h2 class="sr-only">{first ? 'All news' : `All news, page ${page.currentPage}`}</h2>
|
|
<div class="grid">
|
|
{page.data.map((post, i) => <NewsCard post={post} featured={first && i === 0} />)}
|
|
</div>
|
|
{page.lastPage > 1 && (
|
|
<nav class="pagination" aria-label="News pages">
|
|
{page.url.prev
|
|
? <a class="page-link page-step" href={page.url.prev} rel="prev">← Newer</a>
|
|
: <span class="page-link page-step" aria-hidden="true">← Newer</span>}
|
|
<ol>
|
|
{nums.map((n) => (
|
|
<li>
|
|
{n === 0
|
|
? <span class="page-gap" aria-hidden="true">…</span>
|
|
: <a class="page-link" href={hrefFor(n)} aria-current={n === page.currentPage ? 'page' : undefined}><span class="sr-only">Page </span>{n}</a>}
|
|
</li>
|
|
))}
|
|
</ol>
|
|
{page.url.next
|
|
? <a class="page-link page-step" href={page.url.next} rel="next">Older →</a>
|
|
: <span class="page-link page-step" aria-hidden="true">Older →</span>}
|
|
</nav>
|
|
)}
|
|
</section>
|
|
</Base>
|