slug eingeführt
This commit is contained in:
parent
2e16f61b3b
commit
d1c87db4f7
13 changed files with 81 additions and 50 deletions
|
|
@ -1,9 +1,8 @@
|
||||||
---
|
---
|
||||||
import type { Post } from "../types/global";
|
|
||||||
import PostPreviewSmall from "./PostPreviewSmall.astro";
|
import PostPreviewSmall from "./PostPreviewSmall.astro";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
posts: Array<Post>;
|
posts: Array<any>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { posts } = Astro.props;
|
const { posts } = Astro.props;
|
||||||
|
|
@ -12,7 +11,7 @@ const { posts } = Astro.props;
|
||||||
<div class="post-grid">
|
<div class="post-grid">
|
||||||
{
|
{
|
||||||
posts.map((post_file: any) => (
|
posts.map((post_file: any) => (
|
||||||
<PostPreviewSmall url={post_file.url} post={post_file.frontmatter} />
|
<PostPreviewSmall post={post_file.data} />
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,14 @@
|
||||||
---
|
---
|
||||||
import type { Post } from "../types/global";
|
|
||||||
import { findImageByPath } from "../lib/findImage";
|
import { findImageByPath } from "../lib/findImage";
|
||||||
import { Image } from "astro:assets";
|
import { Image } from "astro:assets";
|
||||||
import { formatLocalizedDateString } from "../lib/formatDate";
|
import { formatLocalizedDateString } from "../lib/formatDate";
|
||||||
|
import type { PostData } from "../content.config";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
post: Post;
|
post: PostData;
|
||||||
url: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const { post, url } = Astro.props;
|
const { post } = Astro.props;
|
||||||
|
|
||||||
const img = findImageByPath(post.image.path);
|
const img = findImageByPath(post.image.path);
|
||||||
const localeDate = formatLocalizedDateString(post.date)
|
const localeDate = formatLocalizedDateString(post.date)
|
||||||
|
|
@ -17,12 +16,12 @@ const localeDate = formatLocalizedDateString(post.date)
|
||||||
|
|
||||||
<div class="wide-container">
|
<div class="wide-container">
|
||||||
<div class="image-col col rounded">
|
<div class="image-col col rounded">
|
||||||
<a href={url}>
|
<a href={`/blog/${post.slug}`}>
|
||||||
<Image src={img} alt={post.image.alt} layout="constrained" />
|
<Image src={img} alt={post.image.alt} layout="constrained" />
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-col col">
|
<div class="text-col col">
|
||||||
<a href={url} class="headline-link">
|
<a href={`/blog/${post.slug}`} class="headline-link">
|
||||||
<h2 class="headline">{post.title}</h2>
|
<h2 class="headline">{post.title}</h2>
|
||||||
</a>
|
</a>
|
||||||
<h7>{post.subtitle}</h7>
|
<h7>{post.subtitle}</h7>
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,19 @@
|
||||||
---
|
---
|
||||||
|
import type { PostData } from "../content.config";
|
||||||
import { findImageByPath } from "../lib/findImage";
|
import { findImageByPath } from "../lib/findImage";
|
||||||
import { formatLocalizedDateString } from "../lib/formatDate";
|
import { formatLocalizedDateString } from "../lib/formatDate";
|
||||||
import type { Post } from "../types/global";
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
post: Post;
|
post: PostData;
|
||||||
url: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const { post, url } = Astro.props;
|
const { post } = Astro.props;
|
||||||
|
|
||||||
const img = findImageByPath(post.image.path)
|
const img = findImageByPath(post.image.path)
|
||||||
const localeDate = formatLocalizedDateString(post.date)
|
const localeDate = formatLocalizedDateString(post.date)
|
||||||
---
|
---
|
||||||
|
|
||||||
<a href={url} class="no-link-link">
|
<a href={`/blog/${post.slug}`} class="no-link-link">
|
||||||
<div class="frame rounded">
|
<div class="frame rounded">
|
||||||
<img src={img.src} alt={post.image.alt} class="rounded" />
|
<img src={img.src} alt={post.image.alt} class="rounded" />
|
||||||
<h2 class="headline">{post.title}</h2>
|
<h2 class="headline">{post.title}</h2>
|
||||||
|
|
|
||||||
29
blog/src/content.config.ts
Normal file
29
blog/src/content.config.ts
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
import { defineCollection } from 'astro:content';
|
||||||
|
import { glob } from 'astro/loaders';
|
||||||
|
import { z } from 'astro/zod';
|
||||||
|
|
||||||
|
|
||||||
|
const postSchema = z.object({
|
||||||
|
title: z.string(),
|
||||||
|
subtitle: z.string(),
|
||||||
|
description: z.string(),
|
||||||
|
image: z.object({
|
||||||
|
path: z.string(),
|
||||||
|
alt: z.string()
|
||||||
|
}),
|
||||||
|
author: z.string(),
|
||||||
|
date: z.coerce.date(),
|
||||||
|
slug: z.string(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export type PostData = z.infer<typeof postSchema>;
|
||||||
|
|
||||||
|
const posts = defineCollection({
|
||||||
|
loader: glob({
|
||||||
|
pattern: "**/*.md",
|
||||||
|
base: "./src/pages/blog/",
|
||||||
|
}),
|
||||||
|
schema: postSchema
|
||||||
|
});
|
||||||
|
|
||||||
|
export const collections = { posts };
|
||||||
|
|
@ -2,12 +2,12 @@
|
||||||
import { Image } from "astro:assets";
|
import { Image } from "astro:assets";
|
||||||
import BackNav from "../components/BackNav.astro";
|
import BackNav from "../components/BackNav.astro";
|
||||||
import { findImageByPath } from "../lib/findImage";
|
import { findImageByPath } from "../lib/findImage";
|
||||||
import type { Post } from "../types/global";
|
|
||||||
import Main from "./Main.astro";
|
import Main from "./Main.astro";
|
||||||
import { formatLocalizedDateString } from "../lib/formatDate";
|
import { formatLocalizedDateString } from "../lib/formatDate";
|
||||||
|
import type { PostData } from "../content.config";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
frontmatter: Post;
|
frontmatter: PostData;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { frontmatter } = Astro.props;
|
const { frontmatter } = Astro.props;
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
export function formatLocalizedDateString(date: string): string {
|
export function formatLocalizedDateString(date: Date): string {
|
||||||
return new Date(date).toLocaleDateString('de-DE')
|
return date.toLocaleDateString('de-DE')
|
||||||
}
|
}
|
||||||
|
|
@ -1,12 +1,14 @@
|
||||||
---
|
---
|
||||||
layout: ../../layouts/BlogPostLayout.astro
|
layout: ../../layouts/BlogPostLayout.astro
|
||||||
title: Under Construction
|
title: Under Construction
|
||||||
|
subtitle: Wir bauen für Sie
|
||||||
description: Bald könnt ihr hier unsere ersten Abenteuer mitverfolgen. Und keine Sorge...an der Webseite wird auch noch gearbeitet!
|
description: Bald könnt ihr hier unsere ersten Abenteuer mitverfolgen. Und keine Sorge...an der Webseite wird auch noch gearbeitet!
|
||||||
image:
|
image:
|
||||||
path: construction.png
|
path: construction.png
|
||||||
alt: Under Construction
|
alt: Under Construction
|
||||||
author: Tim
|
author: Tim
|
||||||
date: '2026-07-10'
|
date: '2026-07-10'
|
||||||
|
slug: Under-Construction
|
||||||
---
|
---
|
||||||
|
|
||||||
# All Endings Are Beginnings
|
# All Endings Are Beginnings
|
||||||
|
|
@ -8,6 +8,7 @@ image:
|
||||||
alt: Chiara und Tim vor einem Strand
|
alt: Chiara und Tim vor einem Strand
|
||||||
author: Tim
|
author: Tim
|
||||||
date: '2026-08-20'
|
date: '2026-08-20'
|
||||||
|
slug: Ostseeurlaub
|
||||||
---
|
---
|
||||||
|
|
||||||
Eigentlich soll es hier um unser (zukünftiges) Boot und die Segelreisen gehen.
|
Eigentlich soll es hier um unser (zukünftiges) Boot und die Segelreisen gehen.
|
||||||
|
|
@ -8,6 +8,7 @@ image:
|
||||||
alt: Chiara und Tim in der nähe der Bergeralm mit tollen Bergen im Hintergrund.
|
alt: Chiara und Tim in der nähe der Bergeralm mit tollen Bergen im Hintergrund.
|
||||||
author: Tim
|
author: Tim
|
||||||
date: '2026-08-29'
|
date: '2026-08-29'
|
||||||
|
slug: Luxusurlaub-in-Matrei
|
||||||
---
|
---
|
||||||
|
|
||||||
Was könnte ein besser Kontrast zum Zelturlaub an der Ostsee sein, als eine Woche in einem luxuriösen Hotel, mitten in den Alpen?<br />
|
Was könnte ein besser Kontrast zum Zelturlaub an der Ostsee sein, als eine Woche in einem luxuriösen Hotel, mitten in den Alpen?<br />
|
||||||
24
blog/src/pages/blog/[slug].astro
Normal file
24
blog/src/pages/blog/[slug].astro
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
---
|
||||||
|
import { getCollection, render } from "astro:content";
|
||||||
|
import BlogPostLayout from "../../layouts/BlogPostLayout.astro";
|
||||||
|
|
||||||
|
export async function getStaticPaths() {
|
||||||
|
const posts = await getCollection("posts");
|
||||||
|
|
||||||
|
return posts.map((post) => ({
|
||||||
|
params: {
|
||||||
|
slug: post.data.slug,
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
post,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
const { post } = Astro.props;
|
||||||
|
const { Content } = await render(post);
|
||||||
|
---
|
||||||
|
|
||||||
|
<BlogPostLayout frontmatter={post.data}>
|
||||||
|
<Content />
|
||||||
|
</BlogPostLayout>
|
||||||
|
|
@ -2,32 +2,21 @@
|
||||||
import Main from "../layouts/Main.astro";
|
import Main from "../layouts/Main.astro";
|
||||||
import PostPreviewLarge from "../components/PostPreviewLarge.astro";
|
import PostPreviewLarge from "../components/PostPreviewLarge.astro";
|
||||||
import PostGrid from "../components/PostGrid.astro";
|
import PostGrid from "../components/PostGrid.astro";
|
||||||
import type { Post } from "../types/global";
|
import { getCollection } from "astro:content";
|
||||||
import { date, readonly } from "astro:schema";
|
|
||||||
|
|
||||||
const allPosts: Array<any> = Object.values(
|
const allPostsSorted = (await getCollection('posts')).sort(
|
||||||
import.meta.glob("./posts/*.md", { eager: true })
|
(postA, postB) =>
|
||||||
|
postB.data.date.getTime() - postA.data.date.getTime()
|
||||||
);
|
);
|
||||||
|
|
||||||
const sortedPosts = allPosts.slice(0, allPosts.length - 1)
|
const [mostRecentPost, ...sortedPosts] = allPostsSorted;
|
||||||
.sort((postA: any, postB: any): number => {
|
|
||||||
const dateA = new Date(postA.frontmatter.date)
|
|
||||||
const dateB = new Date(postB.frontmatter.date)
|
|
||||||
|
|
||||||
if (dateA > dateB) return -1
|
console.log(mostRecentPost.data)
|
||||||
else if (dateA < dateB) return 1
|
|
||||||
return 0
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const mostRecentPost = allPosts.at(allPosts.length - 1);
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<Main title="Startseite">
|
<Main title="Startseite">
|
||||||
<PostPreviewLarge
|
<PostPreviewLarge
|
||||||
url={mostRecentPost.url}
|
post={mostRecentPost.data}
|
||||||
post={mostRecentPost.frontmatter}
|
|
||||||
/>
|
/>
|
||||||
<PostGrid posts={sortedPosts} />
|
<PostGrid posts={sortedPosts} />
|
||||||
</Main>
|
</Main>
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import rss, { pagesGlobToRssItems } from '@astrojs/rss';
|
||||||
export async function GET(context) {
|
export async function GET(context) {
|
||||||
|
|
||||||
const posts = Object.values(
|
const posts = Object.values(
|
||||||
import.meta.glob("./posts/*.md", { eager: true })
|
import.meta.glob("./blog/*.md", { eager: true })
|
||||||
);
|
);
|
||||||
|
|
||||||
return rss({
|
return rss({
|
||||||
|
|
@ -15,7 +15,7 @@ export async function GET(context) {
|
||||||
subtitle: post.frontmatter.subtitle,
|
subtitle: post.frontmatter.subtitle,
|
||||||
pubDate: Date.parse(post.frontmatter.date),
|
pubDate: Date.parse(post.frontmatter.date),
|
||||||
description: post.frontmatter.description,
|
description: post.frontmatter.description,
|
||||||
link: post.url,
|
link: `/blog/${post.frontmatter.slug}`
|
||||||
})),
|
})),
|
||||||
customData: `<language>de-de</language>`,
|
customData: `<language>de-de</language>`,
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
export interface Post {
|
|
||||||
title: String,
|
|
||||||
subtitle: String,
|
|
||||||
description: String,
|
|
||||||
date: string,
|
|
||||||
author: String,
|
|
||||||
image: {
|
|
||||||
path: string,
|
|
||||||
alt: string
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Add table
Reference in a new issue