simon-einzinger.de/docs/.vitepress/theme/composables/cv.data.ts
2025-01-29 22:02:53 +01:00

70 lines
1.7 KiB
TypeScript

import { createContentLoader } from "vitepress";
interface ProjectLink {
label: string;
url: string;
}
interface CVItemData {
section: "education" | "work-experience" | "projects";
institution?: string;
degree?: string;
company?: string;
position?: string;
title?: string;
links?: ProjectLink[];
technologies?: string[];
start: string;
end?: string;
startValue: number;
endValue?: number;
excerpt?: string;
url: string;
body?: string;
}
declare const data: CVItemData[];
export { data };
export default createContentLoader("cv/*.md", {
excerpt: true,
transform(raw) {
return raw.map(({ frontmatter, url, excerpt: autoExcerpt }) => {
const section = frontmatter.section as CVItemData["section"];
const startRaw = frontmatter.start as string;
const endRaw = (frontmatter.end as string) || "";
const startValue = parseMonthYear(startRaw);
const endValue =
endRaw.toLowerCase() === "present" ? Infinity : parseMonthYear(endRaw);
const finalExcerpt = frontmatter.excerpt || autoExcerpt || "";
const links = frontmatter.links ?? [];
const technologies = frontmatter.technologies ?? [];
return {
...frontmatter,
section,
url,
excerpt: finalExcerpt,
start: startRaw,
end: endRaw,
startValue,
endValue,
links,
technologies,
};
}) as CVItemData[];
},
});
function parseMonthYear(str: string): number {
if (!str) return 0;
const [mm, yyyy] = str.split("/");
const month = parseInt(mm, 10);
const year = parseInt(yyyy, 10);
if (isNaN(month) || isNaN(year)) return 0;
return year * 100 + month;
}