From 2df67b6c50f42eb0756cce819fb7b05596284a1f Mon Sep 17 00:00:00 2001 From: hoelee Date: Mon, 21 Sep 2026 21:57:10 +0800 Subject: [PATCH] Fix listing sort order: order by pubDate, matching the date displayed Listings render `pubDate` but sorted by `updatedDate ?? pubDate`, so any post carrying both dates sorted by a date it never displayed. After the backdate commit the two diverged by years and the list read out of order ("January 7, 2026" above "September 13, 2026", "March 11, 2026" below "December 10, 2025"). Replace `sortByUpdated` with `sortForListing`, which orders by `pubDate` and uses `updatedDate` only as a tiebreak. This matches the RSS feed, which already sorted by `pubDate`. Verified all three listings (EN, EN homepage, ZH) are monotonically non-increasing across the full 2024-09 -> 2026-09 span. --- src/lib/sort.ts | 31 ++++++++++++++++++------ src/pages/categories/[category].astro | 4 +-- src/pages/index.astro | 4 +-- src/pages/posts/index.astro | 4 +-- src/pages/zh/categories/[category].astro | 4 +-- src/pages/zh/index.astro | 4 +-- 6 files changed, 34 insertions(+), 17 deletions(-) diff --git a/src/lib/sort.ts b/src/lib/sort.ts index 2393a3b..5905e59 100644 --- a/src/lib/sort.ts +++ b/src/lib/sort.ts @@ -2,16 +2,33 @@ import type { CollectionEntry } from 'astro:content'; type Post = CollectionEntry<'posts'>; +/** + * Newest-first ordering for listings. + * + * Ordered by `pubDate` — the date the listing actually *renders* — so the + * visible order always matches the visible dates. `updatedDate` is only a + * tiebreak, for stable ordering when two posts share a publish date. + * + * Do NOT sort by `updatedDate ?? pubDate` here: listings display `pubDate`, + * so a revised-and-backdated post would sort by a date it never shows and the + * list would read out of order (e.g. "January 7, 2026" appearing above + * "September 13, 2026"). + */ +export function sortForListing(posts: Post[]): Post[] { + return [...posts].sort((a, b) => { + const byPub = b.data.pubDate.valueOf() - a.data.pubDate.valueOf(); + if (byPub !== 0) return byPub; + const aUpd = a.data.updatedDate?.valueOf() ?? 0; + const bUpd = b.data.updatedDate?.valueOf() ?? 0; + return bUpd - aUpd; + }); +} + /** * Effective "last updated" timestamp for a post — `updatedDate` when present, - * else `pubDate`. Used to sort listings newest-first by *update time*, so a - * revised post resurfaces to the top. + * else `pubDate`. Used where *recency of editing* is what matters (e.g. + * deciding whether a post resurfaced), NOT for rendering order. */ export function updatedAt(post: Post): Date { return post.data.updatedDate ?? post.data.pubDate; } - -/** Sort posts newest-first by update time (updatedDate ?? pubDate). */ -export function sortByUpdated(posts: Post[]): Post[] { - return [...posts].sort((a, b) => updatedAt(b).valueOf() - updatedAt(a).valueOf()); -} diff --git a/src/pages/categories/[category].astro b/src/pages/categories/[category].astro index 0187904..3750440 100644 --- a/src/pages/categories/[category].astro +++ b/src/pages/categories/[category].astro @@ -5,7 +5,7 @@ import PostList from '../../components/PostList.astro'; import CategoryArt from '../../components/CategoryArt.astro'; import { getCollection } from 'astro:content'; import { isEn } from '../../lib/lang'; -import { sortByUpdated } from '../../lib/sort'; +import { sortForListing } from '../../lib/sort'; import { categoryMeta } from '../../lib/categories'; export async function getStaticPaths() { @@ -17,7 +17,7 @@ export async function getStaticPaths() { const { category } = Astro.params; const meta = categoryMeta(category as string); -const posts = sortByUpdated( +const posts = sortForListing( (await getCollection('posts', isEn)).filter((p) => p.data.category === category), ); diff --git a/src/pages/index.astro b/src/pages/index.astro index da864b9..9763541 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -4,9 +4,9 @@ import PostList from '../components/PostList.astro'; import { getCollection } from 'astro:content'; import { isEn } from '../lib/lang'; import { SITE } from '../config'; -import { sortByUpdated } from '../lib/sort'; +import { sortForListing } from '../lib/sort'; -const posts = sortByUpdated(await getCollection('posts', isEn)); +const posts = sortForListing(await getCollection('posts', isEn)); --- diff --git a/src/pages/posts/index.astro b/src/pages/posts/index.astro index 66bd8e9..3ec7f91 100644 --- a/src/pages/posts/index.astro +++ b/src/pages/posts/index.astro @@ -3,10 +3,10 @@ import BaseLayout from '../../layouts/BaseLayout.astro'; import PostList from '../../components/PostList.astro'; import { getCollection } from 'astro:content'; import { isEn } from '../../lib/lang'; -import { sortByUpdated } from '../../lib/sort'; +import { sortForListing } from '../../lib/sort'; import { SITE } from '../../config'; -const posts = sortByUpdated(await getCollection('posts', isEn)); +const posts = sortForListing(await getCollection('posts', isEn)); --- p.data.category === category), ); diff --git a/src/pages/zh/index.astro b/src/pages/zh/index.astro index 72ecec7..c916c81 100644 --- a/src/pages/zh/index.astro +++ b/src/pages/zh/index.astro @@ -4,9 +4,9 @@ import PostList from '../../components/PostList.astro'; import { getCollection } from 'astro:content'; import { isZh } from '../../lib/lang'; import { SITE } from '../../config'; -import { sortByUpdated } from '../../lib/sort'; +import { sortForListing } from '../../lib/sort'; -const posts = sortByUpdated(await getCollection('posts', isZh)); +const posts = sortForListing(await getCollection('posts', isZh)); ---