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 AmazonBook from './components/AmazonBook.astro';
|
||||||
import AppleTVFlag from './components/AppleTVFlag.astro';
|
import AppleTVFlag from './components/AppleTVFlag.astro';
|
||||||
import Banner from './components/Banner.astro';
|
import Banner from './components/Banner.astro';
|
||||||
|
import BasicImage from './components/BasicImage.astro';
|
||||||
import Blockquote from './components/Blockquote.astro';
|
import Blockquote from './components/Blockquote.astro';
|
||||||
import Book from './components/Book.astro';
|
import Book from './components/Book.astro';
|
||||||
import Bookshelf from './components/Bookshelf.astro';
|
import Bookshelf from './components/Bookshelf.astro';
|
||||||
@@ -38,13 +39,11 @@ import UnorderedList from './components/UnorderedList.astro';
|
|||||||
import Verse from './components/Verse.astro';
|
import Verse from './components/Verse.astro';
|
||||||
|
|
||||||
export const mapping = {
|
export const mapping = {
|
||||||
a: TextLink,
|
|
||||||
ProductLink,
|
|
||||||
AmazonBook,
|
AmazonBook,
|
||||||
AppleTVFlag,
|
AppleTVFlag,
|
||||||
Banner,
|
Banner,
|
||||||
|
BasicImage,
|
||||||
Blockquote,
|
Blockquote,
|
||||||
blockquote: Blockquote,
|
|
||||||
Book,
|
Book,
|
||||||
Bookshelf,
|
Bookshelf,
|
||||||
ColorStack,
|
ColorStack,
|
||||||
@@ -54,6 +53,22 @@ export const mapping = {
|
|||||||
EmailLink,
|
EmailLink,
|
||||||
Figure,
|
Figure,
|
||||||
Flag,
|
Flag,
|
||||||
|
Image,
|
||||||
|
MarkdownImage,
|
||||||
|
MoreLink,
|
||||||
|
NetflixFlag,
|
||||||
|
OdyseeVideo,
|
||||||
|
PrimeVideoFlag,
|
||||||
|
ProductLink,
|
||||||
|
ProjectIntro,
|
||||||
|
Pullquote,
|
||||||
|
Ruby,
|
||||||
|
Spotify,
|
||||||
|
ThemeBox,
|
||||||
|
Verse,
|
||||||
|
YouTube,
|
||||||
|
a: TextLink,
|
||||||
|
blockquote: Blockquote,
|
||||||
h1: Title,
|
h1: Title,
|
||||||
h2: Headline,
|
h2: Headline,
|
||||||
h3: Subheadline,
|
h3: Subheadline,
|
||||||
@@ -61,24 +76,11 @@ export const mapping = {
|
|||||||
h5: Subsubheadline,
|
h5: Subsubheadline,
|
||||||
h6: Subsubheadline,
|
h6: Subsubheadline,
|
||||||
hr: Divider,
|
hr: Divider,
|
||||||
Image,
|
|
||||||
img: MarkdownImage,
|
img: MarkdownImage,
|
||||||
li: ListItem,
|
li: ListItem,
|
||||||
MarkdownImage,
|
|
||||||
MoreLink,
|
|
||||||
NetflixFlag,
|
|
||||||
OdyseeVideo,
|
|
||||||
ol: OrderedList,
|
ol: OrderedList,
|
||||||
p: Text,
|
p: Text,
|
||||||
PrimeVideoFlag,
|
|
||||||
ProjectIntro,
|
|
||||||
Pullquote,
|
|
||||||
Ruby,
|
|
||||||
Spotify,
|
|
||||||
ThemeBox,
|
|
||||||
ul: UnorderedList,
|
ul: UnorderedList,
|
||||||
Verse,
|
|
||||||
YouTube,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Mapping for RSS feed to reduce the size of the feed
|
// Mapping for RSS feed to reduce the size of the feed
|
||||||
@@ -86,6 +88,7 @@ export const rssMapping = {
|
|||||||
AmazonBook,
|
AmazonBook,
|
||||||
AppleTVFlag,
|
AppleTVFlag,
|
||||||
Banner,
|
Banner,
|
||||||
|
BasicImage,
|
||||||
Blockquote,
|
Blockquote,
|
||||||
Book,
|
Book,
|
||||||
Bookshelf,
|
Bookshelf,
|
||||||
|
|||||||
Reference in New Issue
Block a user