diff --git a/.astro/types.d.ts b/.astro/types.d.ts index ac92831..5d8457e 100644 --- a/.astro/types.d.ts +++ b/.astro/types.d.ts @@ -1,211 +1,339 @@ +declare module 'astro:content' { + interface Render { + '.mdx': Promise<{ + Content: import('astro').MarkdownInstance<{}>['Content']; + headings: import('astro').MarkdownHeading[]; + remarkPluginFrontmatter: Record; + }>; + } +} + +declare module 'astro:content' { + interface Render { + '.md': Promise<{ + Content: import('astro').MarkdownInstance<{}>['Content']; + headings: import('astro').MarkdownHeading[]; + remarkPluginFrontmatter: Record; + }>; + } +} + declare module 'astro:content' { export { z } from 'astro/zod'; - export type CollectionEntry = - (typeof entryMap)[C][keyof (typeof entryMap)[C]] & Render; + + type Flatten = T extends { [K: string]: infer U } ? U : never; + + export type CollectionKey = keyof AnyEntryMap; + export type CollectionEntry = Flatten; + + export type ContentCollectionKey = keyof ContentEntryMap; + export type DataCollectionKey = keyof DataEntryMap; + + // This needs to be in sync with ImageMetadata + export type ImageFunction = () => import('astro/zod').ZodObject<{ + src: import('astro/zod').ZodString; + width: import('astro/zod').ZodNumber; + height: import('astro/zod').ZodNumber; + format: import('astro/zod').ZodUnion< + [ + import('astro/zod').ZodLiteral<'png'>, + import('astro/zod').ZodLiteral<'jpg'>, + import('astro/zod').ZodLiteral<'jpeg'>, + import('astro/zod').ZodLiteral<'tiff'>, + import('astro/zod').ZodLiteral<'webp'>, + import('astro/zod').ZodLiteral<'gif'>, + import('astro/zod').ZodLiteral<'svg'>, + import('astro/zod').ZodLiteral<'avif'>, + ] + >; + }>; type BaseSchemaWithoutEffects = | import('astro/zod').AnyZodObject - | import('astro/zod').ZodUnion + | import('astro/zod').ZodUnion<[BaseSchemaWithoutEffects, ...BaseSchemaWithoutEffects[]]> | import('astro/zod').ZodDiscriminatedUnion - | import('astro/zod').ZodIntersection< - import('astro/zod').AnyZodObject, - import('astro/zod').AnyZodObject - >; + | import('astro/zod').ZodIntersection; type BaseSchema = | BaseSchemaWithoutEffects | import('astro/zod').ZodEffects; - type BaseCollectionConfig = { - schema?: S; - slug?: (entry: { - id: CollectionEntry['id']; - defaultSlug: string; - collection: string; - body: string; - data: import('astro/zod').infer; - }) => string | Promise; - }; - export function defineCollection( - input: BaseCollectionConfig - ): BaseCollectionConfig; + export type SchemaContext = { image: ImageFunction }; + + type DataCollectionConfig = { + type: 'data'; + schema?: S | ((context: SchemaContext) => S); + }; + + type ContentCollectionConfig = { + type?: 'content'; + schema?: S | ((context: SchemaContext) => S); + }; + + type CollectionConfig = ContentCollectionConfig | DataCollectionConfig; + + export function defineCollection( + input: CollectionConfig + ): CollectionConfig; - type EntryMapKeys = keyof typeof entryMap; type AllValuesOf = T extends any ? T[keyof T] : never; - type ValidEntrySlug = AllValuesOf<(typeof entryMap)[C]>['slug']; + type ValidContentEntrySlug = AllValuesOf< + ContentEntryMap[C] + >['slug']; export function getEntryBySlug< - C extends keyof typeof entryMap, - E extends ValidEntrySlug | (string & {}) + C extends keyof ContentEntryMap, + E extends ValidContentEntrySlug | (string & {}), >( collection: C, // Note that this has to accept a regular string too, for SSR entrySlug: E - ): E extends ValidEntrySlug + ): E extends ValidContentEntrySlug ? Promise> : Promise | undefined>; - export function getCollection>( + + export function getDataEntryById( + collection: C, + entryId: E + ): Promise>; + + export function getCollection>( collection: C, filter?: (entry: CollectionEntry) => entry is E ): Promise; + export function getCollection( + collection: C, + filter?: (entry: CollectionEntry) => unknown + ): Promise[]>; - type InferEntrySchema = import('astro/zod').infer< - Required['schema'] + export function getEntry< + C extends keyof ContentEntryMap, + E extends ValidContentEntrySlug | (string & {}), + >(entry: { + collection: C; + slug: E; + }): E extends ValidContentEntrySlug + ? Promise> + : Promise | undefined>; + export function getEntry< + C extends keyof DataEntryMap, + E extends keyof DataEntryMap[C] | (string & {}), + >(entry: { + collection: C; + id: E; + }): E extends keyof DataEntryMap[C] + ? Promise + : Promise | undefined>; + export function getEntry< + C extends keyof ContentEntryMap, + E extends ValidContentEntrySlug | (string & {}), + >( + collection: C, + slug: E + ): E extends ValidContentEntrySlug + ? Promise> + : Promise | undefined>; + export function getEntry< + C extends keyof DataEntryMap, + E extends keyof DataEntryMap[C] | (string & {}), + >( + collection: C, + id: E + ): E extends keyof DataEntryMap[C] + ? Promise + : Promise | undefined>; + + /** Resolve an array of entry references from the same collection */ + export function getEntries( + entries: { + collection: C; + slug: ValidContentEntrySlug; + }[] + ): Promise[]>; + export function getEntries( + entries: { + collection: C; + id: keyof DataEntryMap[C]; + }[] + ): Promise[]>; + + export function reference( + collection: C + ): import('astro/zod').ZodEffects< + import('astro/zod').ZodString, + C extends keyof ContentEntryMap + ? { + collection: C; + slug: ValidContentEntrySlug; + } + : { + collection: C; + id: keyof DataEntryMap[C]; + } + >; + // Allow generic `string` to avoid excessive type errors in the config + // if `dev` is not running to update as you edit. + // Invalid collection names will be caught at build time. + export function reference( + collection: C + ): import('astro/zod').ZodEffects; + + type ReturnTypeOrOriginal = T extends (...args: any[]) => infer R ? R : T; + type InferEntrySchema = import('astro/zod').infer< + ReturnTypeOrOriginal['schema']> >; - type Render = { - render(): Promise<{ - Content: import('astro').MarkdownInstance<{}>['Content']; - headings: import('astro').MarkdownHeading[]; - remarkPluginFrontmatter: Record; - }>; - }; - - const entryMap: { + type ContentEntryMap = { "blog": { "summer.mdx": { - id: "summer.mdx", - slug: "summer", - body: string, - collection: "blog", + id: "summer.mdx"; + slug: "summer"; + body: string; + collection: "blog"; data: InferEntrySchema<"blog"> -}, +} & { render(): Render[".mdx"] }; "week1.mdx": { - id: "week1.mdx", - slug: "week1", - body: string, - collection: "blog", + id: "week1.mdx"; + slug: "week1"; + body: string; + collection: "blog"; data: InferEntrySchema<"blog"> -}, +} & { render(): Render[".mdx"] }; "week2.mdx": { - id: "week2.mdx", - slug: "week2", - body: string, - collection: "blog", + id: "week2.mdx"; + slug: "week2"; + body: string; + collection: "blog"; data: InferEntrySchema<"blog"> -}, +} & { render(): Render[".mdx"] }; "week3.mdx": { - id: "week3.mdx", - slug: "week3", - body: string, - collection: "blog", + id: "week3.mdx"; + slug: "week3"; + body: string; + collection: "blog"; data: InferEntrySchema<"blog"> -}, +} & { render(): Render[".mdx"] }; "week4.mdx": { - id: "week4.mdx", - slug: "week4", - body: string, - collection: "blog", + id: "week4.mdx"; + slug: "week4"; + body: string; + collection: "blog"; data: InferEntrySchema<"blog"> -}, +} & { render(): Render[".mdx"] }; "week5-6.mdx": { - id: "week5-6.mdx", - slug: "week5-6", - body: string, - collection: "blog", + id: "week5-6.mdx"; + slug: "week5-6"; + body: string; + collection: "blog"; data: InferEntrySchema<"blog"> -}, +} & { render(): Render[".mdx"] }; "week7-8.mdx": { - id: "week7-8.mdx", - slug: "week7-8", - body: string, - collection: "blog", + id: "week7-8.mdx"; + slug: "week7-8"; + body: string; + collection: "blog"; data: InferEntrySchema<"blog"> -}, +} & { render(): Render[".mdx"] }; "week9-10.mdx": { - id: "week9-10.mdx", - slug: "week9-10", - body: string, - collection: "blog", + id: "week9-10.mdx"; + slug: "week9-10"; + body: string; + collection: "blog"; data: InferEntrySchema<"blog"> -}, +} & { render(): Render[".mdx"] }; "work1.mdx": { - id: "work1.mdx", - slug: "work1", - body: string, - collection: "blog", + id: "work1.mdx"; + slug: "work1"; + body: string; + collection: "blog"; data: InferEntrySchema<"blog"> -}, +} & { render(): Render[".mdx"] }; "work2.mdx": { - id: "work2.mdx", - slug: "work2", - body: string, - collection: "blog", + id: "work2.mdx"; + slug: "work2"; + body: string; + collection: "blog"; data: InferEntrySchema<"blog"> -}, +} & { render(): Render[".mdx"] }; "work3.mdx": { - id: "work3.mdx", - slug: "work3", - body: string, - collection: "blog", + id: "work3.mdx"; + slug: "work3"; + body: string; + collection: "blog"; data: InferEntrySchema<"blog"> -}, +} & { render(): Render[".mdx"] }; "work4.mdx": { - id: "work4.mdx", - slug: "work4", - body: string, - collection: "blog", + id: "work4.mdx"; + slug: "work4"; + body: string; + collection: "blog"; data: InferEntrySchema<"blog"> -}, +} & { render(): Render[".mdx"] }; "work5.mdx": { - id: "work5.mdx", - slug: "work5", - body: string, - collection: "blog", + id: "work5.mdx"; + slug: "work5"; + body: string; + collection: "blog"; data: InferEntrySchema<"blog"> -}, +} & { render(): Render[".mdx"] }; "work6.mdx": { - id: "work6.mdx", - slug: "work6", - body: string, - collection: "blog", + id: "work6.mdx"; + slug: "work6"; + body: string; + collection: "blog"; data: InferEntrySchema<"blog"> -}, +} & { render(): Render[".mdx"] }; "year2022-1.mdx": { - id: "year2022-1.mdx", - slug: "year2022-1", - body: string, - collection: "blog", + id: "year2022-1.mdx"; + slug: "year2022-1"; + body: string; + collection: "blog"; data: InferEntrySchema<"blog"> -}, +} & { render(): Render[".mdx"] }; "year2022-end.mdx": { - id: "year2022-end.mdx", - slug: "year2022-end", - body: string, - collection: "blog", + id: "year2022-end.mdx"; + slug: "year2022-end"; + body: string; + collection: "blog"; data: InferEntrySchema<"blog"> -}, +} & { render(): Render[".mdx"] }; "year2022-w1.mdx": { - id: "year2022-w1.mdx", - slug: "year2022-w1", - body: string, - collection: "blog", + id: "year2022-w1.mdx"; + slug: "year2022-w1"; + body: string; + collection: "blog"; data: InferEntrySchema<"blog"> -}, +} & { render(): Render[".mdx"] }; "year2022-w2.mdx": { - id: "year2022-w2.mdx", - slug: "year2022-w2", - body: string, - collection: "blog", + id: "year2022-w2.mdx"; + slug: "year2022-w2"; + body: string; + collection: "blog"; data: InferEntrySchema<"blog"> -}, +} & { render(): Render[".mdx"] }; "year2022-w3.mdx": { - id: "year2022-w3.mdx", - slug: "year2022-w3", - body: string, - collection: "blog", + id: "year2022-w3.mdx"; + slug: "year2022-w3"; + body: string; + collection: "blog"; data: InferEntrySchema<"blog"> -}, +} & { render(): Render[".mdx"] }; "year2023-1.mdx": { - id: "year2023-1.mdx", - slug: "year2023-1", - body: string, - collection: "blog", + id: "year2023-1.mdx"; + slug: "year2023-1"; + body: string; + collection: "blog"; data: InferEntrySchema<"blog"> -}, -}, +} & { render(): Render[".mdx"] }; +}; }; + type DataEntryMap = { + + }; + + type AnyEntryMap = ContentEntryMap & DataEntryMap; + type ContentConfig = typeof import("../src/content/config"); } diff --git a/astro.config.mjs b/astro.config.mjs index 14d34f4..eac0373 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -1,5 +1,4 @@ import { defineConfig } from "astro/config"; - // https://astro.build/config import mdx from "@astrojs/mdx"; diff --git a/package.json b/package.json index fa1a7b5..7773546 100644 --- a/package.json +++ b/package.json @@ -11,9 +11,11 @@ "astro": "astro" }, "dependencies": { - "@astrojs/mdx": "^0.15.0", + "@astrojs/mdx": "^2.0.2", + "@astrojs/react": "^3.0.8", "@astrojs/rss": "^2.1.0", - "astro": "^2.0.0", + "@rollup/plugin-dynamic-import-vars": "^2.1.2", + "astro": "^4.0.7", "astrojs-service-worker": "^0.0.9" }, "devDependencies": { diff --git a/src/components/Card.astro b/src/components/Card.astro index 0aea694..b0d851e 100644 --- a/src/components/Card.astro +++ b/src/components/Card.astro @@ -1,18 +1,31 @@ --- export interface Props { - title: string; - src: string; + imageData: ImageData, + optimize?: boolean } -const { title, src } = Astro.props; +import { Picture } from 'astro:assets' +import type { ImageData } from './types'; +import { importImage } from './images'; + +const { imageData } = Astro.props; + +const image = importImage(imageData); ---
- {title} + {imageData.title}
- {title} + {typeof image === 'string' && {imageData.title}} + {typeof image !== 'string' && + + + }
@@ -20,4 +33,8 @@ const { title, src } = Astro.props; .card { margin-bottom: 20px; } + .pic { + height: 100%; + width: 100%; + } diff --git a/src/components/Cards.astro b/src/components/Cards.astro index 42050ff..c193a39 100644 --- a/src/components/Cards.astro +++ b/src/components/Cards.astro @@ -1,8 +1,9 @@ --- import Card from "./Card.astro"; +import type { ImageData } from "./types"; export interface Props { - images: { title: string; src: string }[]; + images: ImageData[]; } const { images } = Astro.props; @@ -10,6 +11,8 @@ const { images } = Astro.props;
- {images.map((i) => )} + {images.map((i) => + + )}
diff --git a/src/components/FrontPageLink.astro b/src/components/FrontPageLink.astro index bc919d0..2b04f4d 100644 --- a/src/components/FrontPageLink.astro +++ b/src/components/FrontPageLink.astro @@ -1,20 +1,26 @@ --- export interface Props { - title: string; description: string; - imageSrc: string; + imageData: ImageData; href: string; } +import { Picture } from "astro:assets"; +import type { ImageData } from './types'; +import { importImage } from "./images"; +const { href, imageData, description } = Astro.props; -const { href, title, imageSrc, description } = Astro.props; +const optImage = importImage(imageData); ---
- +
-
{title}
+
{imageData.title}

in which {description}

@@ -58,5 +64,10 @@ const { href, title, imageSrc, description } = Astro.props; .card-text { font-size: medium; } + + .pic { + height: 100%; + width: 100%; + } } diff --git a/src/components/Hero.astro b/src/components/Hero.astro index 04b674a..1ef21e0 100644 --- a/src/components/Hero.astro +++ b/src/components/Hero.astro @@ -1,23 +1,28 @@ --- export interface Props { - title: string; date?: Date; - image: string; + imageData: ImageData; bold?: boolean; } -const { title, date, image, bold = false } = Astro.props; +import { Picture } from 'astro:assets' +import type { ImageData } from './types'; +import { importImage } from './images'; + +const { date, imageData, bold = false } = Astro.props; + +const optImage = importImage(imageData); + const actualDate = date ? new Date(date) : undefined; const dateString = actualDate?.toISOString()?.slice(0, 10); ---
-

{title}

+

{imageData.title}

{date &&
{dateString}
}
- - +