client/components/mma/shared/images/theGrid.ts (42 lines of code) (raw):
import type { $Keys } from 'utility-types';
// ----- Setup ----- //
const catalogue = {
digitalSubPackshot: '71ff2a443acb92047e428782ed0239075fd2007a/0_0_497_285',
googlePlay: '0a3eda7d719ad8ebe3a13a9bab8fd2b3348d1f20/0_0_554_160',
appleAppStore: 'a0787d3b313f03ed87a16ced224ab4022f794bc5/0_0_554_160',
};
export const GRID_DOMAIN = 'https://media.guim.co.uk';
export const imageCatalogue: Record<string, string> = catalogue;
// ----- Types ----- //
export type ImageType = 'jpg' | 'png';
export type GridImage = {
gridId: ImageId;
srcSizes: number[];
imgType: ImageType;
};
export type GridSlot = {
sizes: string;
media: string;
};
export type Source = GridImage & GridSlot;
// Utility type: https://flow.org/en/docs/types/utilities/#toc-keys
export type ImageId = $Keys<typeof imageCatalogue>;
// ----- Functions ----- //
// Builds a grid url from and id and an image size.
// Example: https://media.guim.co.uk/g65756g5/300.jpg
export function gridUrl(
gridId: ImageId,
size: number,
imgType: ImageType = 'jpg',
): string {
const path = `${imageCatalogue[gridId]}/${size}.${imgType}`;
const url = new URL(path, GRID_DOMAIN);
return url.toString();
}
// Returns a series of grid urls and their corresponding sizes.
// Example:
// "https://media.guim.co.uk/g65756g5/300.jpg 300w,
// https://media.guim.co.uk/g65756g5/500.jpg 500w,
// https://media.guim.co.uk/g65756g5/700.jpg 700w"
export function gridSrcset(
gridId: ImageId,
sizes: number[],
imgType?: ImageType,
): string {
const sources = sizes.map(
(size) => `${gridUrl(gridId, size, imgType)} ${size}w`,
);
return sources.join(', ');
}
// ----- Helper functions ----- //
// Ascending comparison function for use with Array.prototype.sort.
export function ascending(a: number, b: number): number {
return a - b;
}