Enhance project structure and functionality by adding new components and integrations. Updated .gitignore to exclude history and transformed images. Integrated Svelte, sitemap, and icon support in astro.config.mjs. Added multiple new components including BlogOverview, ContentRows, Footer, Header, and various block components for improved content management. Updated package.json with new dependencies and modified scripts for build and development processes.

This commit is contained in:
Peter Meier
2026-02-22 12:14:43 +01:00
parent 054b5719e5
commit bb6ec20d45
52 changed files with 12536 additions and 179 deletions
+136
View File
@@ -0,0 +1,136 @@
<script lang="ts">
import MarkdownBlock from "./blocks/MarkdownBlock.svelte";
import HeadlineBlock from "./blocks/HeadlineBlock.svelte";
import HtmlBlock from "./blocks/HtmlBlock.svelte";
import IframeBlock from "./blocks/IframeBlock.svelte";
import ImageBlock from "./blocks/ImageBlock.svelte";
import ImageGalleryBlock from "./blocks/ImageGalleryBlock.svelte";
import YoutubeVideoBlock from "./blocks/YoutubeVideoBlock.svelte";
import QuoteBlock from "./blocks/QuoteBlock.svelte";
import LinkListBlock from "./blocks/LinkListBlock.svelte";
import PostOverviewBlock from "./blocks/PostOverviewBlock.svelte";
import SearchableTextBlock from "./blocks/SearchableTextBlock.svelte";
import { isBlockLayoutBreakout } from "../lib/block-layout";
import type { BlockLayout } from "../lib/block-layout";
import type {
RowContentLayout,
ResolvedBlock,
MarkdownBlockData,
HeadlineBlockData,
HtmlBlockData,
IframeBlockData,
ImageBlockData,
ImageGalleryBlockData,
YoutubeVideoBlockData,
QuoteBlockData,
LinkListBlockData,
PostOverviewBlockData,
SearchableTextBlockData,
} from "../lib/block-types";
let { layout, class: className = "" }: { layout: RowContentLayout; class?: string } = $props();
function isResolvedBlock(item: unknown): item is ResolvedBlock {
return typeof item === "object" && item !== null;
}
function blockType(item: ResolvedBlock): string {
return (item._type as string) ?? "unknown";
}
function justifyToClass(j?: string): string {
switch (j) {
case "end": return "justify-end";
case "center": return "justify-center";
case "between": return "justify-between";
case "around": return "justify-around";
case "evenly": return "justify-evenly";
default: return "justify-start";
}
}
function alignToClass(a?: string): string {
switch (a) {
case "end": return "items-end";
case "center": return "items-center";
case "baseline": return "items-baseline";
case "stretch": return "items-stretch";
default: return "items-start";
}
}
const rows = $derived([
{
content: layout.row1Content ?? [],
justify: justifyToClass(layout.row1JustifyContent),
align: alignToClass(layout.row1AlignItems),
},
{
content: layout.row2Content ?? [],
justify: justifyToClass(layout.row2JustifyContent),
align: alignToClass(layout.row2AlignItems),
},
{
content: layout.row3Content ?? [],
justify: justifyToClass(layout.row3JustifyContent),
align: alignToClass(layout.row3AlignItems),
},
]);
</script>
<div class="content my-6 {className}">
{#each rows as row}
{#if row.content.length > 0}
<div
class="content-row grid grid-cols-12 gap-4 {row.justify} {row.align}"
role="region"
data-cf-type="grid-row"
>
{#each row.content as item}
{#if isResolvedBlock(item)}
{#snippet blockContent()}
{#if blockType(item) === "markdown"}
<MarkdownBlock block={item as MarkdownBlockData} />
{:else if blockType(item) === "headline"}
<HeadlineBlock block={item as HeadlineBlockData} />
{:else if blockType(item) === "html"}
<HtmlBlock block={item as HtmlBlockData} />
{:else if blockType(item) === "iframe"}
<IframeBlock block={item as IframeBlockData} />
{:else if blockType(item) === "image"}
<ImageBlock block={item as ImageBlockData} />
{:else if blockType(item) === "image_gallery"}
<ImageGalleryBlock block={item as ImageGalleryBlockData} />
{:else if blockType(item) === "youtube_video"}
<YoutubeVideoBlock block={item as YoutubeVideoBlockData} />
{:else if blockType(item) === "quote"}
<QuoteBlock block={item as QuoteBlockData} />
{:else if blockType(item) === "link_list"}
<LinkListBlock block={item as LinkListBlockData} />
{:else if blockType(item) === "post_overview"}
<PostOverviewBlock block={item as PostOverviewBlockData} />
{:else if blockType(item) === "searchable_text"}
<SearchableTextBlock block={item as SearchableTextBlockData} />
{:else}
<div class="col-span-12 rounded border border-amber-200 bg-amber-50 px-3 py-2 text-sm text-amber-800">
Unbekannter Block: <code>{blockType(item)}</code>
</div>
{/if}
{/snippet}
{#if isBlockLayoutBreakout((item as { layout?: BlockLayout }).layout)}
<div class="col-span-12">
<div class="w-screen relative left-1/2 -translate-x-1/2 max-w-none bg-linear-to-b from-green-50 to-green-100 border-y border-green-100">
<div class="container-custom py-4">
{@render blockContent()}
</div>
</div>
</div>
{:else}
{@render blockContent()}
{/if}
{/if}
{/each}
</div>
{/if}
{/each}
</div>