From 3b9873e288b5283d45657779a48b5a603121ec6c Mon Sep 17 00:00:00 2001 From: kritzl Date: Tue, 6 Oct 2026 19:45:18 +0200 Subject: [PATCH] improve image handling - add blurred fallback image - define images in dict --- package.json | 2 + pnpm-lock.yaml | 61 ++++++++--- src/pages/hamburg/2026/index.astro | 165 +++++++++++++++++++---------- 3 files changed, 157 insertions(+), 71 deletions(-) diff --git a/package.json b/package.json index 8c02cfd..a1e7cb3 100644 --- a/package.json +++ b/package.json @@ -16,10 +16,12 @@ "@tailwindcss/typography": "^0.5.20", "@tailwindcss/vite": "^4.3.3", "astro": "^7.3.5", + "plaiceholder": "^3.0.0", "sharp": "^0.35.5", "tailwindcss": "^4.3.3" }, "devDependencies": { + "@types/node": "^26.6.4", "daisyui": "^5.7.46" } } \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b15cdba..d63e65a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -10,23 +10,29 @@ importers: dependencies: '@lucide/astro': specifier: ^1.48.0 - version: 1.48.0(astro@7.3.5(jiti@2.7.0)) + version: 1.48.0(astro@7.3.5(@types/node@26.6.4)(jiti@2.7.0)) '@tailwindcss/typography': specifier: ^0.5.20 version: 0.5.20(tailwindcss@4.3.3) '@tailwindcss/vite': specifier: ^4.3.3 - version: 4.3.3(vite@8.3.1(esbuild@0.28.2)(jiti@2.7.0)) + version: 4.3.3(vite@8.3.1(@types/node@26.6.4)(esbuild@0.28.2)(jiti@2.7.0)) astro: specifier: ^7.3.5 - version: 7.3.5(jiti@2.7.0) + version: 7.3.5(@types/node@26.6.4)(jiti@2.7.0) + plaiceholder: + specifier: ^3.0.0 + version: 3.0.0(sharp@0.35.5(@types/node@26.6.4)) sharp: specifier: ^0.35.5 - version: 0.35.5 + version: 0.35.5(@types/node@26.6.4) tailwindcss: specifier: ^4.3.3 version: 4.3.3 devDependencies: + '@types/node': + specifier: ^26.6.4 + version: 26.6.4 daisyui: specifier: ^5.7.46 version: 5.7.46 @@ -813,6 +819,9 @@ packages: '@types/nlcst@2.0.3': resolution: {integrity: sha512-vSYNSDe6Ix3q+6Z7ri9lyWqgGhJTmzRjZRqyq15N0Z/1/UnVsno9G/N40NBijoYx2seFDIl0+B2mgAb9mezUCA==} + '@types/node@26.6.4': + resolution: {integrity: sha512-ldVPDCzj7fsaGZrLB0NuHuTvJcsNasysBAqMolr/cgxrLd1xbqxIr3XJiPnHHJUCxj5sNF1vnRj9aWnrVh5Jcg==} + '@types/unist@3.0.3': resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} @@ -1334,6 +1343,11 @@ packages: resolution: {integrity: sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==} engines: {node: '>=12'} + plaiceholder@3.0.0: + resolution: {integrity: sha512-jwHxxHPnr1BwRzPCeZgEK2BMsEy2327sWynw3qb6XC/oGgGDUTPtR8pFxFQmNArhMBwhkUbUr5OPhhIJpCa8eQ==} + peerDependencies: + sharp: '>= 0.30.6' + postcss-selector-parser@6.0.10: resolution: {integrity: sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==} engines: {node: '>=4'} @@ -1467,6 +1481,9 @@ packages: uncrypto@0.1.3: resolution: {integrity: sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==} + undici-types@8.9.0: + resolution: {integrity: sha512-KTDyRTYX8sWmKXAikPHHSyc63CRPETMctyjKFupcC6OBLXT3xsN0e9aF7m+mIXutFWpUXuedtowG7iLOzp0kQg==} + undici@8.11.2: resolution: {integrity: sha512-u4UB2/IrKdU6lFxumHmmo1a3fCQO5tzQllRorfoRS63txhrB7xTpSn1PftwC4qEHkOaqP95fCWW4lJzwErwzhQ==} engines: {node: '>=22.19.0'} @@ -2012,9 +2029,9 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.6.0 - '@lucide/astro@1.48.0(astro@7.3.5(jiti@2.7.0))': + '@lucide/astro@1.48.0(astro@7.3.5(@types/node@26.6.4)(jiti@2.7.0))': dependencies: - astro: 7.3.5(jiti@2.7.0) + astro: 7.3.5(@types/node@26.6.4)(jiti@2.7.0) '@napi-rs/wasm-runtime@1.2.4(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)': dependencies: @@ -2187,12 +2204,12 @@ snapshots: postcss-selector-parser: 6.0.10 tailwindcss: 4.3.3 - '@tailwindcss/vite@4.3.3(vite@8.3.1(esbuild@0.28.2)(jiti@2.7.0))': + '@tailwindcss/vite@4.3.3(vite@8.3.1(@types/node@26.6.4)(esbuild@0.28.2)(jiti@2.7.0))': dependencies: '@tailwindcss/node': 4.3.3 '@tailwindcss/oxide': 4.3.3 tailwindcss: 4.3.3 - vite: 8.3.1(esbuild@0.28.2)(jiti@2.7.0) + vite: 8.3.1(@types/node@26.6.4)(esbuild@0.28.2)(jiti@2.7.0) '@tybys/wasm-util@0.10.4': dependencies: @@ -2217,6 +2234,10 @@ snapshots: dependencies: '@types/unist': 3.0.3 + '@types/node@26.6.4': + dependencies: + undici-types: 8.9.0 + '@types/unist@3.0.3': {} '@ungap/structured-clone@1.4.0': {} @@ -2234,7 +2255,7 @@ snapshots: aria-query@5.3.2: {} - astro@7.3.5(jiti@2.7.0): + astro@7.3.5(@types/node@26.6.4)(jiti@2.7.0): dependencies: '@astrojs/compiler-rs': 0.5.1 '@astrojs/internal-helpers': 0.11.0 @@ -2284,13 +2305,13 @@ snapshots: unifont: 0.7.5 unstorage: 1.17.5 verkit: 0.4.1 - vite: 8.3.1(esbuild@0.28.2)(jiti@2.7.0) - vitefu: 1.1.3(vite@8.3.1(esbuild@0.28.2)(jiti@2.7.0)) + vite: 8.3.1(@types/node@26.6.4)(esbuild@0.28.2)(jiti@2.7.0) + vitefu: 1.1.3(vite@8.3.1(@types/node@26.6.4)(esbuild@0.28.2)(jiti@2.7.0)) xxhash-wasm: 1.1.0 yargs-parser: 22.0.0 zod: 4.6.5 optionalDependencies: - sharp: 0.35.5 + sharp: 0.35.5(@types/node@26.6.4) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -2756,6 +2777,10 @@ snapshots: picomatch@4.0.7: {} + plaiceholder@3.0.0(sharp@0.35.5(@types/node@26.6.4)): + dependencies: + sharp: 0.35.5(@types/node@26.6.4) + postcss-selector-parser@6.0.10: dependencies: cssesc: 3.0.0 @@ -2837,7 +2862,7 @@ snapshots: semver@7.8.5: {} - sharp@0.35.5: + sharp@0.35.5(@types/node@26.6.4): dependencies: '@img/colour': 1.1.0 detect-libc: 2.1.2 @@ -2868,6 +2893,7 @@ snapshots: '@img/sharp-win32-arm64': 0.35.5 '@img/sharp-win32-ia32': 0.35.5 '@img/sharp-win32-x64': 0.35.5 + '@types/node': 26.6.4 shiki@4.4.3: dependencies: @@ -2931,6 +2957,8 @@ snapshots: uncrypto@0.1.3: {} + undici-types@8.9.0: {} + undici@8.11.2: {} unified@11.0.5: @@ -2997,7 +3025,7 @@ snapshots: '@types/unist': 3.0.3 vfile-message: 4.0.3 - vite@8.3.1(esbuild@0.28.2)(jiti@2.7.0): + vite@8.3.1(@types/node@26.6.4)(esbuild@0.28.2)(jiti@2.7.0): dependencies: lightningcss: 1.33.0 picomatch: 4.0.7 @@ -3005,13 +3033,14 @@ snapshots: rolldown: 1.2.11 tinyglobby: 0.2.17 optionalDependencies: + '@types/node': 26.6.4 esbuild: 0.28.2 fsevents: 2.3.3 jiti: 2.7.0 - vitefu@1.1.3(vite@8.3.1(esbuild@0.28.2)(jiti@2.7.0)): + vitefu@1.1.3(vite@8.3.1(@types/node@26.6.4)(esbuild@0.28.2)(jiti@2.7.0)): optionalDependencies: - vite: 8.3.1(esbuild@0.28.2)(jiti@2.7.0) + vite: 8.3.1(@types/node@26.6.4)(esbuild@0.28.2)(jiti@2.7.0) xxhash-wasm@1.1.0: {} diff --git a/src/pages/hamburg/2026/index.astro b/src/pages/hamburg/2026/index.astro index 17b972f..517bbfb 100644 --- a/src/pages/hamburg/2026/index.astro +++ b/src/pages/hamburg/2026/index.astro @@ -2,38 +2,70 @@ import Footer from "../../../components/Footer.astro" import Layout from "../../../layouts/Layout.astro" import {File} from "@lucide/astro" -import path from "../../../utils/path.ts" +import customPath from "../../../utils/path.ts" import {Picture} from "astro:assets" +import {readFile} from "node:fs/promises" +import {getPlaiceholder} from "plaiceholder" import traumweh_1 from "../../../assets/media/hamburg/2026/traumweh_1.png" -const impressions = [ - { +type Image = { + image: any, + alt: string, + attribution: string, + blur?: string, +} + +const images_raw: Record = { + traumweh_1: { image: traumweh_1, alt: "Ein Foto der Veranstaltung. Eine Speakerin steht auf einer Bühe. Auf einer Leinwand ist eine Präsentation zu sehen. Auf Bannern steht DIDAYS 2026 Hamburg.", attribution: "CC-4.0 BY-SA traumweh", }, - { + traumweh_2: { image: traumweh_1, alt: "Ein Foto der Veranstaltung. Eine Speakerin steht auf einer Bühe. Auf einer Leinwand ist eine Präsentation zu sehen. Auf Bannern steht DIDAYS 2026 Hamburg.", attribution: "CC-4.0 BY-SA traumweh", }, - { + traumweh_3: { image: traumweh_1, alt: "Ein Foto der Veranstaltung. Eine Speakerin steht auf einer Bühe. Auf einer Leinwand ist eine Präsentation zu sehen. Auf Bannern steht DIDAYS 2026 Hamburg.", attribution: "CC-4.0 BY-SA traumweh", }, - { + traumweh_4: { image: traumweh_1, alt: "Ein Foto der Veranstaltung. Eine Speakerin steht auf einer Bühe. Auf einer Leinwand ist eine Präsentation zu sehen. Auf Bannern steht DIDAYS 2026 Hamburg.", attribution: "CC-4.0 BY-SA traumweh", }, - { + traumweh_5: { image: traumweh_1, alt: "Ein Foto der Veranstaltung. Eine Speakerin steht auf einer Bühe. Auf einer Leinwand ist eine Präsentation zu sehen. Auf Bannern steht DIDAYS 2026 Hamburg.", attribution: "CC-4.0 BY-SA traumweh", }, -] +} + +const images: Record = {} + +for (const image_name in images_raw) { + const image = images_raw[image_name] + + let buffer + if (import.meta.env.DEV) { + const imagePath = new URL(image.image.src, Astro.url) + const imageResponse = await fetch(imagePath) + buffer = Buffer.from(await imageResponse.arrayBuffer()) + } else { + const imagePath = "./dist" + image.image.src + buffer = await readFile(imagePath) + } + + image["blur"] = (await getPlaiceholder(buffer, { + size: 10, + })).base64 + images[image_name] = image +} + +const impressions = ["traumweh_1", "traumweh_2", "traumweh_3", "traumweh_4", "traumweh_5"] const slides = [ { @@ -58,7 +90,8 @@ const slides = [

- Logo von den DiDays 2026 in Hamburg

@@ -72,21 +105,31 @@ const slides = [
-
+
+ class="mask-[url(/transitions/small.svg)] bg-base-200 h-10 mask-repeat-x mask-[auto_100%] absolute top-0 w-full z-20"/> + - - CC-4.0 BY-SA traumweh - + {images["traumweh_1"].attribution && + + {images["traumweh_1"].attribution} + + }
+ class="mask-[url(/transitions/small.svg)] bg-base-200 h-10 mask-repeat-x mask-[auto_100%] rotate-180 absolute bottom-0 w-full z-20"/>
@@ -119,42 +162,54 @@ const slides = [ Eindrücke vom Event
- {impressions.map((impression, index) => - - - - -
- { - impression.attribution && - - {impression.attribution} - - } - -
-
- , + + + +
+ { + impression.attribution && + + {impression.attribution} + + } + +
+
) + + }, )}
@@ -171,7 +226,7 @@ const slides = [

{slides.map(slide => -

{slide.name}