🔥 Use Directus Storage Assets Presets only for images
Block the generation of other image sizes from the URL TODO: Block the access to root asset url as it still displays the original file
This commit is contained in:
@@ -1,14 +1,13 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { getAssetUrl } from '$utils/helpers'
|
import { getAssetUrlKey } from '$utils/helpers'
|
||||||
|
|
||||||
export let src: string = undefined
|
export let src: string = undefined
|
||||||
export let id: string = undefined
|
export let id: string = undefined
|
||||||
|
export let sizeKey: string = undefined
|
||||||
export let sizes: Sizes = undefined
|
export let sizes: Sizes = undefined
|
||||||
export let width: number = sizes && sizes.medium && sizes.medium.width
|
export let width: number = sizes && sizes.medium && sizes.medium.width
|
||||||
export let height: number = sizes && sizes.medium && sizes.medium.height
|
export let height: number = sizes && sizes.medium && sizes.medium.height
|
||||||
export let ratio: number = undefined
|
export let ratio: number = undefined
|
||||||
export let quality: number = 80
|
|
||||||
export let fit: string = 'inside'
|
|
||||||
export let alt: string
|
export let alt: string
|
||||||
export let lazy: boolean = true
|
export let lazy: boolean = true
|
||||||
|
|
||||||
@@ -18,6 +17,17 @@
|
|||||||
large?: { width?: number, height?: number }
|
large?: { width?: number, height?: number }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get asset url from size
|
||||||
|
* @description Adds the size and the format to the result
|
||||||
|
* @returns string `id?key={key}-{size}-{format}`
|
||||||
|
*/
|
||||||
|
const getSizeUrl = (key: string, size: string, format: string) => {
|
||||||
|
return getAssetUrlKey(id, `${key}-${size}-${format}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define height from origin ratio if not defined
|
* Define height from origin ratio if not defined
|
||||||
*/
|
*/
|
||||||
@@ -44,28 +54,20 @@
|
|||||||
*/
|
*/
|
||||||
const imgWidth: number = sizes && sizes.small ? sizes.small.width : width
|
const imgWidth: number = sizes && sizes.small ? sizes.small.width : width
|
||||||
const imgHeight: number = sizes && sizes.small ? sizes.small.height : height
|
const imgHeight: number = sizes && sizes.small ? sizes.small.height : height
|
||||||
const imgSrc = id ? getAssetUrl(id, imgWidth, imgHeight, quality, fit, 'jpg') : src ? src : null
|
const imgSrc = id ? getSizeUrl(sizeKey, 'small', 'jpg') : src ? src : null
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<picture class={$$props.class ? $$props.class : ''}>
|
<picture class={$$props.class ? $$props.class : ''}>
|
||||||
<source
|
<source
|
||||||
type="image/webp"
|
type="image/webp"
|
||||||
srcset="
|
srcset="{getSizeUrl(sizeKey, 'small', 'webp')} 345w {sizes && sizes.medium ? `, ${getSizeUrl(sizeKey, 'medium', 'webp')} 768w,` : ''} {sizes && sizes.large ? `, ${getSizeUrl(sizeKey, 'large', 'webp')} 1280w` : ''}"
|
||||||
{getAssetUrl(id, imgWidth, imgHeight, quality, fit, 'webp')} 345w,
|
|
||||||
{sizes && sizes.medium ? `${getAssetUrl(id, sizes.medium.width, sizes.medium.height, quality, fit, 'webp')} 768w,` : ''}
|
|
||||||
{sizes && sizes.large ? `${getAssetUrl(id, sizes.large.width, sizes.large.height, quality, fit, 'webp')} 1280w,` : ''}
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
src={imgSrc}
|
src={imgSrc}
|
||||||
sizes="(min-width: 1200px) 864px, (min-width: 992px) 708px, (min-width: 768px) 540px, 100%"
|
sizes="(min-width: 1200px) 864px, (min-width: 992px) 708px, (min-width: 768px) 540px, 100%"
|
||||||
srcset="
|
srcset="{getSizeUrl(sizeKey, 'small', 'jpg')} 300w {sizes && sizes.medium ? `, ${getSizeUrl(sizeKey, 'medium', 'jpg')} 768w` : ''} {sizes && sizes.large ? `, ${getSizeUrl(sizeKey, 'large', 'jpg')} 1280w` : ''}"
|
||||||
{getAssetUrl(id, imgWidth, imgHeight, quality, fit)} 300w,
|
width={imgWidth}
|
||||||
{sizes && sizes.medium ? `${getAssetUrl(id, sizes.medium.width, sizes.medium.height, quality, fit)} 768w,` : ''}
|
height={imgHeight}
|
||||||
{sizes && sizes.large ? `${getAssetUrl(id, sizes.large.width, sizes.large.height, quality, fit)} 1280w,` : ''}
|
|
||||||
"
|
|
||||||
width={width}
|
|
||||||
height={height}
|
|
||||||
alt={alt}
|
alt={alt}
|
||||||
loading={lazy ? 'lazy' : undefined}
|
loading={lazy ? 'lazy' : undefined}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -55,7 +55,13 @@
|
|||||||
on:mouseleave={handleMouseLeave}
|
on:mouseleave={handleMouseLeave}
|
||||||
sveltekit-noscroll
|
sveltekit-noscroll
|
||||||
>
|
>
|
||||||
<Image class="location__flag" id={location.country.flag.id} alt="Flag of {location.country.name}" width={32} height={32} />
|
<Image
|
||||||
|
class="location__flag"
|
||||||
|
id={location.country.flag.id}
|
||||||
|
sizeKey="square"
|
||||||
|
width={32} height={32}
|
||||||
|
alt="Flag of {location.country.name}"
|
||||||
|
/>
|
||||||
<div class="text">
|
<div class="text">
|
||||||
<dl>
|
<dl>
|
||||||
<dt class="location__name">
|
<dt class="location__name">
|
||||||
@@ -75,8 +81,10 @@
|
|||||||
{#each location.photos as { image }, index}
|
{#each location.photos as { image }, index}
|
||||||
<Image
|
<Image
|
||||||
class={index === photoIndex ? 'is-visible' : null}
|
class={index === photoIndex ? 'is-visible' : null}
|
||||||
id={image.id} alt={image.title}
|
id={image.id}
|
||||||
width={340} height={226} quality={70}
|
sizeKey="photo-thumbnail"
|
||||||
|
width={340} height={226}
|
||||||
|
alt={image.title}
|
||||||
/>
|
/>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
<a href={url}>
|
<a href={url}>
|
||||||
<Image
|
<Image
|
||||||
id={id}
|
id={id}
|
||||||
|
sizeKey="postcard"
|
||||||
{sizes}
|
{sizes}
|
||||||
ratio={1.5}
|
ratio={1.5}
|
||||||
alt={alt}
|
alt={alt}
|
||||||
@@ -25,6 +26,7 @@
|
|||||||
{:else}
|
{:else}
|
||||||
<Image
|
<Image
|
||||||
id={id}
|
id={id}
|
||||||
|
sizeKey="postcard"
|
||||||
{sizes}
|
{sizes}
|
||||||
ratio={1.5}
|
ratio={1.5}
|
||||||
alt={alt}
|
alt={alt}
|
||||||
|
|||||||
@@ -20,7 +20,13 @@
|
|||||||
<div class="frame">
|
<div class="frame">
|
||||||
<img src="/images/icons/stamp.svg" width="32" height="42" alt="Stamp">
|
<img src="/images/icons/stamp.svg" width="32" height="42" alt="Stamp">
|
||||||
</div>
|
</div>
|
||||||
<Image class="flag" id={flagId} width={32} height={32} alt="Flag of {country}" />
|
<Image
|
||||||
|
class="flag"
|
||||||
|
id={flagId}
|
||||||
|
sizeKey="square"
|
||||||
|
width={32} height={32}
|
||||||
|
alt="Flag of {country}"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<ul class="postcard__address">
|
<ul class="postcard__address">
|
||||||
<li>{street}</li>
|
<li>{street}</li>
|
||||||
|
|||||||
@@ -14,7 +14,15 @@
|
|||||||
<div class="shop shadow-box-dark">
|
<div class="shop shadow-box-dark">
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<div class="shop__image">
|
<div class="shop__image">
|
||||||
<Image id={shop.module_image.id} alt={shop.module_image.title} width={800} height={800} />
|
<Image
|
||||||
|
id={shop.module_image.id}
|
||||||
|
sizeKey="square"
|
||||||
|
sizes={{
|
||||||
|
small: { width: 400, height: 400 },
|
||||||
|
large: { width: 800, height: 800 },
|
||||||
|
}}
|
||||||
|
alt={shop.module_image.title}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="shop__content">
|
<div class="shop__content">
|
||||||
|
|||||||
@@ -56,10 +56,11 @@
|
|||||||
<Image
|
<Image
|
||||||
id={currentPhoto.image.id}
|
id={currentPhoto.image.id}
|
||||||
alt={currentPhoto.title}
|
alt={currentPhoto.title}
|
||||||
|
sizeKey="photo-list"
|
||||||
sizes={{
|
sizes={{
|
||||||
small: { width: 500 },
|
small: { width: 500 },
|
||||||
medium: { width: 900 },
|
medium: { width: 850 },
|
||||||
large: { width: 1440 },
|
large: { width: 1280 },
|
||||||
}}
|
}}
|
||||||
ratio={1.5}
|
ratio={1.5}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -3,14 +3,14 @@
|
|||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
import advancedFormat from 'dayjs/plugin/advancedFormat.js'
|
import advancedFormat from 'dayjs/plugin/advancedFormat.js'
|
||||||
import relativeTime from 'dayjs/plugin/relativeTime.js'
|
import relativeTime from 'dayjs/plugin/relativeTime.js'
|
||||||
import { getAssetUrl } from '$utils/helpers'
|
import { getAssetUrlKey } from '$utils/helpers'
|
||||||
// Components
|
// Components
|
||||||
import Button from '$components/atoms/Button.svelte'
|
import Button from '$components/atoms/Button.svelte'
|
||||||
import IconEarth from '$components/atoms/IconEarth.svelte'
|
import IconEarth from '$components/atoms/IconEarth.svelte'
|
||||||
import Image from '$components/atoms/Image.svelte'
|
import Image from '$components/atoms/Image.svelte'
|
||||||
import Newsletter from '$components/organisms/Newsletter.svelte'
|
import Newsletter from '$components/organisms/Newsletter.svelte'
|
||||||
|
|
||||||
export let data: any
|
export let location: any
|
||||||
export let photos: any[]
|
export let photos: any[]
|
||||||
export let lastUpdated: string
|
export let lastUpdated: string
|
||||||
export let totalPhotos: number
|
export let totalPhotos: number
|
||||||
@@ -88,9 +88,9 @@
|
|||||||
<main class="location-page">
|
<main class="location-page">
|
||||||
<section class="location-page__intro grid"
|
<section class="location-page__intro grid"
|
||||||
style="
|
style="
|
||||||
--illus-desktop: url({getAssetUrl(data.illustration_desktop.id, 1600, 1466, 90)});
|
--illus-desktop: url({getAssetUrlKey(location.illustration_desktop.id, 'illustration-desktop-1x')});
|
||||||
--illus-desktop-2x: url({getAssetUrl(data.illustration_desktop_2x.id, 3200, 2932, 90)});
|
--illus-desktop-2x: url({getAssetUrlKey(location.illustration_desktop_2x.id, 'illustration-desktop-2x')});
|
||||||
--illus-mobile: url({getAssetUrl(data.illustration_mobile.id, 1125, 2317, 90)});
|
--illus-mobile: url({getAssetUrlKey(location.illustration_mobile.id, 'illustration-mobile')});
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<h1 class="title">
|
<h1 class="title">
|
||||||
@@ -99,19 +99,19 @@
|
|||||||
<span>of</span>
|
<span>of</span>
|
||||||
</span>
|
</span>
|
||||||
<strong class="city">
|
<strong class="city">
|
||||||
{data.name}
|
{location.name}
|
||||||
</strong>
|
</strong>
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<div class="location-page__description grid" bind:this={descriptionEl}>
|
<div class="location-page__description grid" bind:this={descriptionEl}>
|
||||||
<div class="wrap">
|
<div class="wrap">
|
||||||
<div class="text-medium">
|
<div class="text-medium">
|
||||||
Houses of {data.name} {data.description}
|
Houses of {location.name} {location.description}
|
||||||
</div>
|
</div>
|
||||||
<div class="info">
|
<div class="info">
|
||||||
<p class="text-label">
|
<p class="text-label">
|
||||||
Photos by
|
Photos by
|
||||||
{#each data.credits as { credit_id: { name, website }}}
|
{#each location.credits as { credit_id: { name, website }}}
|
||||||
{#if website}
|
{#if website}
|
||||||
<a href={website} target="_blank" rel="noopener external">
|
<a href={website} target="_blank" rel="noopener external">
|
||||||
{name}
|
{name}
|
||||||
@@ -159,19 +159,25 @@
|
|||||||
</time>
|
</time>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<a class="house__photo" href="/{params.country}/{params.location}/{slug}">
|
<div class="photo house__photo shadow-photo">
|
||||||
|
<a href="/{params.country}/{params.location}/{slug}">
|
||||||
<Image
|
<Image
|
||||||
id={id}
|
id={id}
|
||||||
|
sizeKey="photo-list"
|
||||||
|
sizes={{
|
||||||
|
small: { width: 500 },
|
||||||
|
medium: { width: 850 },
|
||||||
|
large: { width: 1280 },
|
||||||
|
}}
|
||||||
|
ratio={1.5}
|
||||||
alt="{alt}"
|
alt="{alt}"
|
||||||
width={1280}
|
|
||||||
height={853}
|
|
||||||
class="shadow-photo"
|
|
||||||
/>
|
/>
|
||||||
<span class="house__index title-index">
|
<span class="house__index title-index">
|
||||||
{(totalPhotos - index < 10) ? '0' : ''}{totalPhotos - index}
|
{(totalPhotos - index < 10) ? '0' : ''}{totalPhotos - index}
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@@ -199,7 +205,7 @@
|
|||||||
{:else}
|
{:else}
|
||||||
<div class="location-page__message">
|
<div class="location-page__message">
|
||||||
<p>
|
<p>
|
||||||
No photos available for {data.name}.<br>
|
No photos available for {location.name}.<br>
|
||||||
Come back later!
|
Come back later!
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -268,7 +274,7 @@
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
props: {
|
props: {
|
||||||
data: data.location[0],
|
location: data.location[0],
|
||||||
photos: data.photos,
|
photos: data.photos,
|
||||||
totalPhotos: data.photos.length ? locationPhotosCount.count.id : 0,
|
totalPhotos: data.photos.length ? locationPhotosCount.count.id : 0,
|
||||||
lastUpdated: data.photos.length ? data.photos[0].date_created : undefined,
|
lastUpdated: data.photos.length ? data.photos[0].date_created : undefined,
|
||||||
|
|||||||
@@ -202,7 +202,13 @@
|
|||||||
value={filterCountry}
|
value={filterCountry}
|
||||||
>
|
>
|
||||||
{#if countryFlagId}
|
{#if countryFlagId}
|
||||||
<Image id={countryFlagId} width={26} height={26} alt="{filterCountry} flag" class="icon" />
|
<Image
|
||||||
|
class="icon"
|
||||||
|
id={countryFlagId}
|
||||||
|
sizeKey="square"
|
||||||
|
width={26} height={26}
|
||||||
|
alt="{filterCountry} flag"
|
||||||
|
/>
|
||||||
{:else}
|
{:else}
|
||||||
<IconEarth class="icon" />
|
<IconEarth class="icon" />
|
||||||
{/if}
|
{/if}
|
||||||
@@ -262,6 +268,7 @@
|
|||||||
<a href="/{location.country.slug}/{location.slug}/{slug}">
|
<a href="/{location.country.slug}/{location.slug}/{slug}">
|
||||||
<Image
|
<Image
|
||||||
id={image.id}
|
id={image.id}
|
||||||
|
sizeKey="photo-grid"
|
||||||
sizes={{
|
sizes={{
|
||||||
small: { width: 500 },
|
small: { width: 500 },
|
||||||
medium: { width: 900 },
|
medium: { width: 900 },
|
||||||
|
|||||||
@@ -29,7 +29,12 @@
|
|||||||
{#each issues as { issue, title, date_sent, link, thumbnail: { id } }}
|
{#each issues as { issue, title, date_sent, link, thumbnail: { id } }}
|
||||||
<li class="issue">
|
<li class="issue">
|
||||||
<a href={link} target="_blank" rel="external noreferrer noopener">
|
<a href={link} target="_blank" rel="external noreferrer noopener">
|
||||||
<Image id={id} width={160} height={112} alt="Issue {issue} thumbnail" />
|
<Image
|
||||||
|
id={id}
|
||||||
|
sizeKey="issue-thumbnail"
|
||||||
|
width={160} height={112}
|
||||||
|
alt="Issue {issue} thumbnail"
|
||||||
|
/>
|
||||||
<dl>
|
<dl>
|
||||||
<dt>Issue #{issue}</dt>
|
<dt>Issue #{issue}</dt>
|
||||||
<dd>
|
<dd>
|
||||||
|
|||||||
@@ -20,3 +20,14 @@ export const getAssetUrl = (
|
|||||||
|
|
||||||
return `${API_URL}/assets/${id}?width=${width}&height=${height}&fit=${fit}${args}`
|
return `${API_URL}/assets/${id}?width=${width}&height=${height}&fit=${fit}${args}`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a Directus asset URL from parameters
|
||||||
|
*/
|
||||||
|
export const getAssetUrlKey = (
|
||||||
|
id: string,
|
||||||
|
key: string
|
||||||
|
) => {
|
||||||
|
return `${API_URL}/assets/${id}?key=${key}`
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user