eratic / sites / home / src / lib / latest.ts
278 words
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
import { getCollection } from 'astro:content';
import { SITES } from '@eratic/core';

export interface Latest {
	title: string;
	summary: string;
	pubDate: Date;
	/** Absolute — these point at another origin. */
	href: string;
	kicker?: string;
}

function isPublished(data: { draft: boolean; pubDate: Date }): boolean {
	if (import.meta.env.DEV) return true;
	return !data.draft && data.pubDate.getTime() <= Date.now();
}

function newestFirst(a: Latest, b: Latest): number {
	return b.pubDate.getTime() - a.pubDate.getTime();
}

/** Posts and photo sets from blog.eratic.ro, interleaved as they are there. */
export async function latestFromBlog(limit = 4): Promise<Latest[]> {
	const [posts, photos] = await Promise.all([getCollection('posts'), getCollection('photos')]);

	const items: Latest[] = [
		...posts.filter((e) => isPublished(e.data)).map((e) => ({
			title: e.data.title,
			summary: e.data.summary,
			pubDate: e.data.pubDate,
			href: new URL(`/${e.id}/`, SITES.blog.url).href,
			kicker: 'Writing',
		})),
		...photos.filter((e) => isPublished(e.data)).map((e) => {
			const count = e.data.photos?.length ?? 0;
			const place = e.data.place ? `${e.data.place}, ` : '';
			return {
				title: e.data.title,
				summary: e.data.summary,
				pubDate: e.data.pubDate,
				href: new URL(`/${e.id}/`, SITES.blog.url).href,
				kicker: count ? `${place}${count} photograph${count === 1 ? '' : 's'}` : 'Photographs',
			};
		}),
	];

	return items.sort(newestFirst).slice(0, limit);
}

export async function latestFromFav(limit = 4): Promise<Latest[]> {
	const favs = await getCollection('favs');
	return favs
		.filter((e) => isPublished(e.data))
		.map((e) => ({
			title: e.data.title,
			summary: e.data.summary,
			pubDate: e.data.pubDate,
			href: new URL(`/${e.id}/`, SITES.fav.url).href,
			kicker: [e.data.kind.charAt(0).toUpperCase() + e.data.kind.slice(1), e.data.creator]
				.filter(Boolean)
				.join(' · '),
		}))
		.sort(newestFirst)
		.slice(0, limit);
}

export async function latestFromIo(limit = 3): Promise<Latest[]> {
	const issues = await getCollection('issues');
	return issues
		.filter((e) => isPublished(e.data))
		.map((e) => {
			const count = e.data.links?.length ?? 0;
			return {
				title: e.data.title ?? `Issue ${e.data.issue}`,
				summary: e.data.summary,
				pubDate: e.data.pubDate,
				href: new URL(`/${e.id}/`, SITES.io.url).href,
				kicker: count ? `${count} thing${count === 1 ? '' : 's'}` : undefined,
			};
		})
		.sort(newestFirst)
		.slice(0, limit);
}

static mirror of HEAD · about · clone: git clone https://git.makefuture.ro/eratic.git