Initial SvelteKit frontend port of windwiderstand.de
Full parity with Astro site: content rows, post/tag routes, pagination, event badges + OSM map, comments, Live-Search via /api/search-index, CMS image proxy, RSS, sitemap. Deploy: Dockerfile + docker-compose.prod.yml + Gitea Actions workflow to build + push to git.pm86.de registry and ssh-deploy to Contabo.
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
<script lang="ts">
|
||||
import { getBlockLayoutClasses } from "$lib/block-layout";
|
||||
import type { ImageBlockData } from "$lib/block-types";
|
||||
import CmsImage from "$lib/components/CmsImage.svelte";
|
||||
|
||||
let { block }: { block: ImageBlockData } = $props();
|
||||
|
||||
/** Rohe Bild-Quelle für /cms-images (URL, //-URL oder Asset-Dateiname/Slug). */
|
||||
function getRawSrc(b: ImageBlockData): string | null {
|
||||
const img = b.img ?? b.image;
|
||||
if (typeof img === "string") {
|
||||
const s = img.trim();
|
||||
if (!s) return null;
|
||||
return s.startsWith("//") ? `https:${s}` : s;
|
||||
}
|
||||
if (img && typeof img === "object") {
|
||||
const src =
|
||||
(img as { src?: string }).src ?? (img as { file?: { url?: string } }).file?.url;
|
||||
if (typeof src === "string" && src)
|
||||
return src.startsWith("//") ? `https:${src}` : src;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
const layoutClasses = $derived(getBlockLayoutClasses(block.layout));
|
||||
const imageSource = $derived(block.image ?? block.img);
|
||||
const rawSrc = $derived(getRawSrc(block));
|
||||
$effect(() => {
|
||||
if (!rawSrc && block._slug) {
|
||||
console.warn("[ImageBlock] Bild nicht verfügbar:", block._slug, {
|
||||
hasImage: !!block.image,
|
||||
hasImg: !!block.img,
|
||||
imageType: typeof block.image,
|
||||
imgType: typeof block.img,
|
||||
imgSrc:
|
||||
block.img && typeof block.img === "object"
|
||||
? (block.img as { src?: string }).src
|
||||
: undefined,
|
||||
imageSrc:
|
||||
block.image && typeof block.image === "object"
|
||||
? (block.image as { src?: string }).src
|
||||
: undefined,
|
||||
});
|
||||
}
|
||||
});
|
||||
const title = $derived(
|
||||
typeof imageSource === "object" && imageSource
|
||||
? "description" in imageSource && imageSource.description
|
||||
? imageSource.description
|
||||
: "title" in imageSource
|
||||
? (imageSource as { title?: string }).title
|
||||
: undefined
|
||||
: undefined,
|
||||
);
|
||||
</script>
|
||||
|
||||
<div class={layoutClasses} data-block-type="image" data-block-slug={block._slug}>
|
||||
{#if rawSrc}
|
||||
<figure class="max-w-[400px]">
|
||||
<CmsImage
|
||||
src={rawSrc}
|
||||
width={800}
|
||||
format="webp"
|
||||
quality={85}
|
||||
fit="contain"
|
||||
alt={block.caption ?? title ?? ""}
|
||||
class="w-full rounded-sm"
|
||||
loading="lazy"
|
||||
/>
|
||||
{#if block.caption}
|
||||
<figcaption class="mt-1 text-sm text-zinc-600">{block.caption}</figcaption>
|
||||
{/if}
|
||||
</figure>
|
||||
{:else}
|
||||
<p class="text-sm text-zinc-500">Bild nicht verfügbar.</p>
|
||||
{/if}
|
||||
</div>
|
||||
Reference in New Issue
Block a user