summaryrefslogtreecommitdiff
path: root/src/lib/collection/helpers.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/collection/helpers.ts')
-rw-r--r--src/lib/collection/helpers.ts172
1 files changed, 172 insertions, 0 deletions
diff --git a/src/lib/collection/helpers.ts b/src/lib/collection/helpers.ts
index 587180b..0bfd3c8 100644
--- a/src/lib/collection/helpers.ts
+++ b/src/lib/collection/helpers.ts
@@ -13,6 +13,12 @@ import { createKeyFromArmor } from "../pgp/create.ts";
import { getUserIDsFromKey } from "../pgp/user.ts";
import type { UserIDPacket } from "openpgp";
import { getCollection } from "astro:content";
+import {
+ GetStaticPaths,
+ GetStaticPathsItem,
+ GetStaticPathsResult,
+} from "astro";
+import { getEntry } from "astro:content";
export function getLastUpdate({ data }: CollectionEntry<"blog">): Date {
return data.dateUpdated ?? data.dateCreated;
@@ -108,3 +114,169 @@ export const isTranslation = (
export const isMicro = (
entry: CollectionEntry<"blog">,
): entry is MicroEntry => entry.data.kind === "micro";
+
+export async function getTranslationOriginal(
+ translation: TranslationEntry,
+): Promise<OriginalEntry | undefined> {
+ if (!isTranslation(translation)) {
+ throw new Error();
+ }
+ return await getEntry(translation.data.translationOf);
+}
+
+export const datePaths = (async (): Promise<
+ {
+ params: { date?: string };
+ props: {
+ posts: OriginalEntry[];
+ next?: string;
+ previous?: string;
+ years: number[];
+ months: number[];
+ days?: number[];
+ };
+ }[]
+> => {
+ const posts = await fromPosts(isEntry, identity);
+
+ const archive = {
+ years: new Set<number>(),
+ monthsByYear: new Map<string, Set<number>>(),
+ daysByMonth: new Map<string, Set<number>>(),
+ postsByDate: new Map<string, typeof posts>(),
+ sortedDates: [] as string[],
+ };
+
+ const getYMD = (date: Date) => {
+ const y = date.getFullYear();
+ const m = date.getMonth() + 1;
+ const d = date.getDate();
+ return { y, m, d };
+ };
+
+ for (const post of posts) {
+ const { y, m, d } = getYMD(post.data.dateCreated);
+
+ archive.years.add(y);
+
+ const months = archive.monthsByYear.get(y.toString());
+ if (months === undefined) {
+ archive.monthsByYear.set(y.toString(), new Set([m]));
+ } else {
+ months.add(m);
+ }
+
+ const ym = `${y}/${String(m).padStart(2, "0")}`;
+ const days = archive.daysByMonth.get(ym);
+ if (days === undefined) {
+ archive.daysByMonth.set(ym, new Set([d]));
+ } else {
+ days.add(d);
+ }
+
+ const ymd = `${ym}/${String(d).padStart(2, "0")}`;
+ const posts = archive.postsByDate.get(ymd);
+ if (posts === undefined) {
+ archive.postsByDate.set(ymd, [post]);
+ } else {
+ posts.push(post);
+ }
+ }
+
+ archive.sortedDates = Array.from(archive.postsByDate.keys()).sort();
+
+ const paths: {
+ params: { date?: string };
+ props: {
+ posts: OriginalEntry[];
+ next?: string;
+ previous?: string;
+ years: number[];
+ months: number[];
+ days?: number[];
+ };
+ }[] = [] satisfies GetStaticPathsItem[];
+
+ const sortedYears = Array.from(archive.years).sort();
+
+ const lastYear = Math.max(...sortedYears.map(Number));
+ paths.push({
+ params: { date: undefined },
+ props: {
+ posts: posts.filter((p) => p.data.dateCreated.getFullYear() === lastYear),
+ next: undefined,
+ previous: sortedYears?.[sortedYears.length - 2]?.toString(),
+ years: sortedYears,
+ months: Array.from(archive.monthsByYear.get(lastYear.toString()) ?? []),
+ },
+ });
+
+ for (const y of sortedYears) {
+ const yearPosts = posts.filter((p) =>
+ p.data.dateCreated.getFullYear() === Number(y)
+ );
+ const idx = sortedYears.indexOf(y);
+ paths.push({
+ params: { date: y.toString() },
+ props: {
+ posts: yearPosts,
+ next: sortedYears?.[idx + 1]?.toString(),
+ previous: sortedYears?.[idx - 1]?.toString(),
+ years: sortedYears,
+ months: Array.from(archive.monthsByYear.get(y.toString()) ?? []),
+ },
+ });
+ }
+
+ const allMonths = Array.from(archive.monthsByYear.entries())
+ .flatMap(([year, mset]) =>
+ Array.from(mset).map((m) => `${year}/${String(m).padStart(2, "0")}`)
+ )
+ .sort();
+
+ for (const [y, months] of archive.monthsByYear) {
+ const sortedMonths = Array.from(months).sort();
+ for (const m of sortedMonths) {
+ const monthPosts = posts.filter((p) => {
+ const d = p.data.dateCreated;
+ return (
+ d.getFullYear() === Number(y) &&
+ d.getMonth() + 1 === m
+ );
+ });
+
+ const ym = `${y}/${String(m).padStart(2, "0")}`;
+ const idx = allMonths.indexOf(ym);
+
+ paths.push({
+ params: { date: ym },
+ props: {
+ posts: monthPosts,
+ next: allMonths?.[idx + 1],
+ previous: allMonths?.[idx - 1],
+ years: sortedYears,
+ months: Array.from(months).sort(),
+ days: Array.from(archive.daysByMonth.get(ym) ?? []).sort(),
+ },
+ });
+ }
+ }
+
+ for (let i = 0; i < archive.sortedDates.length; i++) {
+ const ymd = archive.sortedDates[i];
+ const [y, m] = ymd.split("/");
+ paths.push({
+ params: { date: ymd },
+ props: {
+ posts: archive.postsByDate.get(ymd) ?? [],
+ next: archive.sortedDates?.[i + 1],
+ previous: archive.sortedDates?.[i - 1],
+ years: sortedYears,
+ months: Array.from(archive.monthsByYear.get(y) ?? []).sort(),
+ days: Array.from(archive.daysByMonth.get(`${y}/${m}`) ?? []).sort(),
+ },
+ });
+ }
+
+ return paths;
+}) satisfies GetStaticPaths;