mirror of
https://github.com/kogakure/website-astro-stefanimhoff.de.git
synced 2026-02-03 12:05:28 +00:00
feat: add basic image component using the picture of Astro
This commit is contained in:
committed by
Stefan Imhoff
parent
a05dec6363
commit
c5c1b15013
120
src/components/BasicImage.astro
Normal file
120
src/components/BasicImage.astro
Normal file
@@ -0,0 +1,120 @@
|
||||
---
|
||||
import { Picture } from 'astro:assets';
|
||||
import type { ImageMetadata } from 'astro';
|
||||
import TextLink from './TextLink.astro';
|
||||
|
||||
interface Props {
|
||||
alt?: string;
|
||||
caption?: string;
|
||||
class?: string;
|
||||
decoding?: 'async' | 'sync' | 'auto';
|
||||
height?: string | number;
|
||||
loading?: 'lazy' | 'eager';
|
||||
noSpacing?: boolean;
|
||||
quality?: number;
|
||||
size?: 'regular' | 'wide' | 'fullsize';
|
||||
source?: string;
|
||||
sourceUrl?: string;
|
||||
src: string;
|
||||
width?: string | number;
|
||||
}
|
||||
|
||||
const {
|
||||
alt,
|
||||
caption,
|
||||
class: className,
|
||||
decoding = 'async',
|
||||
height,
|
||||
loading = 'lazy',
|
||||
noSpacing,
|
||||
quality,
|
||||
size,
|
||||
source,
|
||||
sourceUrl,
|
||||
src,
|
||||
width,
|
||||
...props
|
||||
} = Astro.props;
|
||||
|
||||
// Normalize dimensions
|
||||
const parseDim = (dim: string | number | undefined) => (dim ? Number(dim) : undefined);
|
||||
const parsedWidth = parseDim(width);
|
||||
const parsedHeight = parseDim(height);
|
||||
|
||||
// Resolve Image Source
|
||||
let localImage: ImageMetadata | undefined;
|
||||
let remoteImage: string = src;
|
||||
|
||||
// Get all the image metadata
|
||||
const images = import.meta.glob<{ default: ImageMetadata }>('/src/images/**/*');
|
||||
|
||||
if (src.startsWith('/images')) {
|
||||
const key = '/src' + src;
|
||||
const loader = images[key as keyof typeof images];
|
||||
|
||||
if (typeof loader === 'function') {
|
||||
const mod = await loader();
|
||||
localImage = mod.default;
|
||||
}
|
||||
}
|
||||
|
||||
// Define sizes attribute for responsive images
|
||||
const sizes = '(max-width: 440px) 100vw, (max-width: 768px) 90vw, (max-width: 1024px) 85vw, 1100px';
|
||||
---
|
||||
|
||||
<figure
|
||||
class:list={[
|
||||
'mbs-0 mie-0 mis-0',
|
||||
{
|
||||
'figure-wide': size === 'wide',
|
||||
'figure-fullsize': size === 'fullsize',
|
||||
'mbe-13': true,
|
||||
},
|
||||
className,
|
||||
]}
|
||||
{...props}
|
||||
>
|
||||
<div class="figure-content flex flex-wrap gap-6 md:flex-nowrap [&_div]:flex-grow">
|
||||
{
|
||||
localImage ? (
|
||||
<Picture
|
||||
alt={alt ?? ''}
|
||||
class="rounded-2"
|
||||
decoding={decoding}
|
||||
formats={['avif', 'webp', 'jpg', 'png']}
|
||||
loading={loading}
|
||||
quality={quality}
|
||||
sizes={sizes}
|
||||
src={localImage}
|
||||
width={parsedWidth}
|
||||
height={parsedHeight}
|
||||
/>
|
||||
) : (
|
||||
<img
|
||||
alt={alt ?? ''}
|
||||
class="rounded-2"
|
||||
loading={loading}
|
||||
src={remoteImage}
|
||||
width={parsedWidth}
|
||||
height={parsedHeight}
|
||||
/>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
{
|
||||
(caption || source) && (
|
||||
<figcaption class="text-center text-2 mbs-2 [text-wrap:balance]">
|
||||
{caption}
|
||||
{caption && source ? '–' : ''}
|
||||
{source &&
|
||||
(sourceUrl ? (
|
||||
<cite>
|
||||
<TextLink href={sourceUrl}>{source}</TextLink>
|
||||
</cite>
|
||||
) : (
|
||||
<cite>{source}</cite>
|
||||
))}
|
||||
</figcaption>
|
||||
)
|
||||
}
|
||||
</figure>
|
||||
@@ -3,6 +3,7 @@ import { YouTube } from '@astro-community/astro-embed-youtube';
|
||||
import AmazonBook from './components/AmazonBook.astro';
|
||||
import AppleTVFlag from './components/AppleTVFlag.astro';
|
||||
import Banner from './components/Banner.astro';
|
||||
import BasicImage from './components/BasicImage.astro';
|
||||
import Blockquote from './components/Blockquote.astro';
|
||||
import Book from './components/Book.astro';
|
||||
import Bookshelf from './components/Bookshelf.astro';
|
||||
@@ -38,13 +39,11 @@ import UnorderedList from './components/UnorderedList.astro';
|
||||
import Verse from './components/Verse.astro';
|
||||
|
||||
export const mapping = {
|
||||
a: TextLink,
|
||||
ProductLink,
|
||||
AmazonBook,
|
||||
AppleTVFlag,
|
||||
Banner,
|
||||
BasicImage,
|
||||
Blockquote,
|
||||
blockquote: Blockquote,
|
||||
Book,
|
||||
Bookshelf,
|
||||
ColorStack,
|
||||
@@ -54,6 +53,22 @@ export const mapping = {
|
||||
EmailLink,
|
||||
Figure,
|
||||
Flag,
|
||||
Image,
|
||||
MarkdownImage,
|
||||
MoreLink,
|
||||
NetflixFlag,
|
||||
OdyseeVideo,
|
||||
PrimeVideoFlag,
|
||||
ProductLink,
|
||||
ProjectIntro,
|
||||
Pullquote,
|
||||
Ruby,
|
||||
Spotify,
|
||||
ThemeBox,
|
||||
Verse,
|
||||
YouTube,
|
||||
a: TextLink,
|
||||
blockquote: Blockquote,
|
||||
h1: Title,
|
||||
h2: Headline,
|
||||
h3: Subheadline,
|
||||
@@ -61,24 +76,11 @@ export const mapping = {
|
||||
h5: Subsubheadline,
|
||||
h6: Subsubheadline,
|
||||
hr: Divider,
|
||||
Image,
|
||||
img: MarkdownImage,
|
||||
li: ListItem,
|
||||
MarkdownImage,
|
||||
MoreLink,
|
||||
NetflixFlag,
|
||||
OdyseeVideo,
|
||||
ol: OrderedList,
|
||||
p: Text,
|
||||
PrimeVideoFlag,
|
||||
ProjectIntro,
|
||||
Pullquote,
|
||||
Ruby,
|
||||
Spotify,
|
||||
ThemeBox,
|
||||
ul: UnorderedList,
|
||||
Verse,
|
||||
YouTube,
|
||||
};
|
||||
|
||||
// Mapping for RSS feed to reduce the size of the feed
|
||||
@@ -86,6 +88,7 @@ export const rssMapping = {
|
||||
AmazonBook,
|
||||
AppleTVFlag,
|
||||
Banner,
|
||||
BasicImage,
|
||||
Blockquote,
|
||||
Book,
|
||||
Bookshelf,
|
||||
|
||||
Reference in New Issue
Block a user