Files
homepage/content-collections.ts
2025-05-14 14:35:15 +02:00

90 lines
3.1 KiB
TypeScript

import { defineCollection, defineConfig } from "@content-collections/core";
import { parsePostDate } from "@/lib/blog";
const italianDateRegex = /^\d{1,2} (gennaio|febbraio|marzo|aprile|maggio|giugno|luglio|agosto|settembre|ottobre|novembre|dicembre) \d{4}$/i;
// Regex per "8 min", "12 min", ecc.
const readTimeRegex = /^\d{1,3} min$/;
const authors = defineCollection({
name: "authors",
directory: "src/authors",
include: "*.yml",
parser: "yaml",
schema: (z) => ({
name: z.string().min(1, "Nome obbligatorio"),
ref: z.string().min(1, "Riferimento obbligatorio"),
avatar: z.string(),
title: z.string().min(1, "Titolo obbligatorio"),
description: z.string().min(1, "Descrizione obbligatoria"),
socialLinks: z.object({
twitter: z.string().url("URL non valido").optional(),
github: z.string().url("URL non valido").optional(),
linkedin: z.string().url("URL non valido").optional(),
}).optional(),
}),
transform(data, context) {
return {
...data,
avatar: `${data.avatar}?height=80&width=80`,
}
},
});
const posts = defineCollection({
name: "posts",
directory: "src/posts",
include: "**/*.md",
schema: (z) => ({
title: z.string().min(1, "Titolo obbligatorio"),
excerpt: z.string().min(1, "Excerpt obbligatorio"),
content: z.string().min(1),
author: z.string().min(1, "Autore obbligatorio"),
date: z.string().regex(italianDateRegex, "La data deve essere nel formato 'dd mmm yyyy'"),
readTime: z.string().regex(readTimeRegex, "readTime deve essere nel formato 'X min'").optional(),
category: z.string().min(1, "Categoria obbligatoria"),
tags: z.array(z.string().min(1)).min(1, "Almeno un tag è richiesto"),
coverImage: z.string(),
hidden: z.null().optional(),
}),
transform(data, context) {
const date = parsePostDate(data.date);
const prefix = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, "0")}-${String(date.getDate()).padStart(2, "0")}`;
const authorObj = context.documents(authors).find((author) => author.ref === data.author);
if (authorObj == null) throw new Error(`Autore non trovato: ${data.author}`);
if (data.readTime == null) {
const words = data.content.trim().split(/\s+/).length;
const wpm = 180;
const minutes = Math.ceil(words / wpm);
data.readTime = `${minutes} min`;
}
return {
...data,
slug: `${prefix}-${data._meta.path}`,
dateObject: date,
author: authorObj,
}
}
});
const portfolio = defineCollection({
name: "portfolio",
directory: "src/portfolio",
include: "**/*.md",
schema: (z) => ({
title: z.string().min(1, "Nome obbligatorio"),
description: z.string().min(1, "Descrizione obbligatoria"),
content: z.string().min(1),
image: z.string(),
tags: z.array(z.string().min(1)).min(1, "Almeno un tag è richiesto"),
year: z.number().min(2000, "L'anno deve essere maggiore di 2000"),
links: z.object({
apple: z.string().url().or(z.null()),
play: z.string().url().or(z.null()),
}).or(z.null()),
}),
});
export default defineConfig({
collections: [authors, posts, portfolio],
});