internal.ts (2320B)
1 import { getCollection, type CollectionEntry } from 'astro:content'; 2 3 export type Internal = CollectionEntry<'internal'>; 4 5 export async function allInternal(): Promise<Internal[]> { 6 return await getCollection('internal'); 7 } 8 9 /** Route (relative to base) for an internal entry. Index -> section root. */ 10 export function internalHref(entry: Internal): string { 11 const id = entry.id.replace(/\/index$/, ''); 12 return `internal/${id}`; 13 } 14 15 /** Pages upstream keeps at the docs root (DISCLAIMER) — in no section. */ 16 export async function internalRootPages(): Promise<Internal[]> { 17 return (await allInternal()) 18 .filter((e) => !e.id.includes('/')) 19 .sort((a, b) => a.data.title.localeCompare(b.data.title)); 20 } 21 22 export interface SectionGroup { 23 slug: string; 24 title: string; 25 index?: Internal; 26 items: Internal[]; // sub-pages (excludes index), alpha 27 count: number; // total pages incl. index 28 } 29 30 /** Pages grouped by section, sections alpha, index first inside a section. */ 31 export async function internalBySection(): Promise<SectionGroup[]> { 32 const all = await allInternal(); 33 const map = new Map<string, Internal[]>(); 34 for (const p of all) { 35 if (!p.id.includes('/')) continue; // root page, not a section member 36 const arr = map.get(p.data.sectionSlug) ?? []; 37 arr.push(p); 38 map.set(p.data.sectionSlug, arr); 39 } 40 const groups: SectionGroup[] = []; 41 for (const [slug, entries] of map) { 42 const index = entries.find((e) => e.data.isIndex); 43 const items = entries 44 .filter((e) => !e.data.isIndex) 45 .sort((a, b) => a.data.title.localeCompare(b.data.title)); 46 groups.push({ 47 slug, 48 title: index?.data.section ?? entries[0].data.section, 49 index, 50 items, 51 count: entries.length, 52 }); 53 } 54 return groups.sort((a, b) => a.title.localeCompare(b.title)); 55 } 56 57 /** Ordered pages within a section (index first) for prev/next. */ 58 export function sectionOrder(group: SectionGroup): Internal[] { 59 return [...(group.index ? [group.index] : []), ...group.items]; 60 } 61 62 export function prevNext(order: Internal[], current: Internal): { prev?: Internal; next?: Internal } { 63 const i = order.findIndex((p) => p.id === current.id); 64 return { 65 prev: i > 0 ? order[i - 1] : undefined, 66 next: i >= 0 && i < order.length - 1 ? order[i + 1] : undefined, 67 }; 68 }