Skip to content

Commit

Permalink
Fix thumbnail generation for website entries
Browse files Browse the repository at this point in the history
This was accomplished by moving the thumbnail generation (using
vite-imagetools) from the server to the client. This is supposedly
because SvelteKit does not currently have support for loading non-raw
assets on the server side (per
<sveltejs/kit#5240>). At least, moving the
logic to the front end worked like a charm.
  • Loading branch information
caleb531 committed Feb 12, 2023
1 parent dc82473 commit fed812e
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 32 deletions.
24 changes: 1 addition & 23 deletions src/lib/entries.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import type { ContactLinkEntry, Entry, ProjectEntry, WebsiteEntry } from '../rou

type EntryType = 'contact_link' | 'project' | 'website';
type GlobMap = Record<string, () => Promise<unknown>>;
type ImagetoolsResult = { default: string[] };
type EntriesByTypeMap = Record<EntryType, GlobMap>;

// A map where each key name a specific entry type (e.g. project) and each value
Expand All @@ -14,18 +13,6 @@ const entriesByType: EntriesByTypeMap = {
website: import.meta.glob('../websites/*.json', { as: 'raw' })
};

// Resize the website images at build time so that the appropriate (smaller)
// versions of each website image can be served
const resizedWebsiteUrlMap: Record<string, ImagetoolsResult> = import.meta.glob(
'../images/websites/*.jpg',
{
// Generate additional sizes for each pregenerated website image
query: { format: 'jpg', width: '256;512' },
// Resolve each import promise and store the final values
eager: true
}
);

// Compute the entry ID from the given path
function getEntryIdFromPath(entryPath: string) {
return entryPath.slice(entryPath.lastIndexOf('/') + 1, entryPath.indexOf('.json'));
Expand Down Expand Up @@ -59,14 +46,5 @@ export async function getContactLinks(): Promise<ContactLinkEntry[]> {
}

export async function getWebsiteEntries(): Promise<WebsiteEntry[]> {
const websiteEntries = await getEntries<WebsiteEntry>('website');
return websiteEntries.map((website) => {
const [image_url_1x, image_url_2x] =
resizedWebsiteUrlMap[`../images/websites/${website.id}.jpg`].default;
return {
...website,
image_url_1x,
image_url_2x
};
});
return getEntries<WebsiteEntry>('website');
}
6 changes: 1 addition & 5 deletions src/routes/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,7 @@ export interface WebsiteEntry extends Entry {
start_year: number;
end_year: number;
}
export interface ResizedWebsiteEntry extends WebsiteEntry {
image_url_1x: string;
image_url_2x: string;
}
export type WebsiteMap = EntryMap<ResizedWebsiteEntry>;
export type WebsiteMap = EntryMap<WebsiteEntry>;

export type ContactLinkEntry = Entry;
export type ContactLinkMap = EntryMap<ContactLinkEntry>;
9 changes: 5 additions & 4 deletions src/routes/websites/Website.svelte
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
<script lang="ts">
import { websiteFade } from '../transitions';
import type { ResizedWebsiteEntry } from '../types';
export let website: ResizedWebsiteEntry;
import type { WebsiteEntry } from '../types';
import { getWebsite1xThumbnailUrl, getWebsite2xThumbnailUrl } from './WebsiteImageStore';
export let website: WebsiteEntry;
</script>

<article data-entry-id={website.id} class="entry website">
<a class="entry-image" href={website.direct_url} in:websiteFade aria-hidden="true" tabindex="-1">
<img
src={website.image_url_1x}
srcset="{website.image_url_2x} 2x"
src={getWebsite1xThumbnailUrl(website)}
srcset="{getWebsite2xThumbnailUrl(website)} 2x"
alt=""
width={256}
height={160}
Expand Down
30 changes: 30 additions & 0 deletions src/routes/websites/WebsiteImageStore.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { get, readable, type Readable } from 'svelte/store';
import type { WebsiteEntry } from '../types';

type ImagetoolsResult = { default: string[] };
type GlobUrlStore = Readable<Record<string, ImagetoolsResult>>;

// Resize the website images at build time so that the appropriate (smaller)
// versions of each website image can be served
export const resizedWebsiteUrlMap: GlobUrlStore = readable(
import.meta.glob('../../images/websites/*.jpg', {
// Generate additional sizes for each pregenerated website image
query: { format: 'jpg', width: '256;512' },
// Resolve each import promise and store the final values
eager: true
})
);

// Retrieve the URL to the regular-sized thumbnail for this website
export function getWebsite1xThumbnailUrl(website: WebsiteEntry): string {
const $resizedWebsiteUrlMap = get(resizedWebsiteUrlMap);
const imagePath = `../../images/websites/${website.id}.jpg`;
return $resizedWebsiteUrlMap[imagePath].default[0];
}

// Retrieve the URL to the high-density (Retina) thumbnail for this website
export function getWebsite2xThumbnailUrl(website: WebsiteEntry): string {
const $resizedWebsiteUrlMap = get(resizedWebsiteUrlMap);
const imagePath = `../../images/websites/${website.id}.jpg`;
return $resizedWebsiteUrlMap[imagePath].default[1];
}

0 comments on commit fed812e

Please sign in to comment.