/** The resume's data, shared by the page and the PDF so they never disagree. */ import type { Note } from "./content.ts"; import type { SiteIndex } from "./site.ts"; export interface ResumeData { name: string; headline: string; location?: string; summary?: string; availability?: string; email?: string; stats: { value: string; label: string; detail?: string }[]; /** Roles shown in full, current first. */ roles: Note<"experience">[]; /** Roles marked earlier: a short list of title, company, dates and focus. */ earlier: Note<"experience">[]; projects: { title: string; detail: string; link?: string }[]; skills?: Note<"skills">["data"]; education?: Note<"education">["data"]; socials: { label: string; handle: string; url: string }[]; /** The newest change to any note the resume is built from (YYYY-MM-DD). */ updated: string; } /** "Mar 2019", from "2019-03". */ export const month = (ym: string | undefined) => { if (!ym) return "Present"; const [y, m] = ym.split("-").map(Number); return new Date(Date.UTC(y!, (m ?? 1) - 1, 1)).toLocaleDateString("en-US", { timeZone: "UTC", month: "short", year: "numeric" }); }; export const period = (r: Note<"experience">) => `${month(r.data.start)} – ${month(r.data.end)}`; /** "A, B and C". */ export const listOf = (items: string[]) => new Intl.ListFormat("en-US", { style: "long", type: "conjunction" }).format(items); export function resumeData(s: SiteIndex): ResumeData { const settings = s.settings(); const page = s.pageText("/resume"); const roles = [...s.all("experience")].sort((a, b) => (b.data.end ?? "9999").localeCompare(a.data.end ?? "9999") || b.data.start.localeCompare(a.data.start)); const current = roles.find((r) => !r.data.end) ?? roles[0]; const sources: Note[] = [...roles, ...(page ? [page] : []), ...[s.one("skills"), s.one("education")].filter((n): n is Note<"skills"> | Note<"education"> => !!n)]; const updated = sources.map((n) => n.acceptedAt?.slice(0, 10) ?? "").sort().at(-1) ?? ""; return { name: settings?.name ?? "Greg Kilmer", headline: page?.data.lede ?? current?.data.role ?? "", location: settings?.location, summary: page?.body?.trim() || undefined, availability: settings?.availability, email: settings?.email, stats: page?.data.stats ?? [], roles: roles.filter((r) => !r.data.earlier), earlier: roles.filter((r) => r.data.earlier), projects: page?.data.projects ?? [], skills: s.one("skills")?.data, education: s.one("education")?.data, socials: settings?.socials ?? [], updated, }; }