import { boostSize } from "./boost" export type MediaFormat = "webp" | "avif" | "jpeg" | "png" export type MediaFit = "cover" | "contain" | "fill" | "inside" | "outside" export type MediaParams = { width?: number | `${number}` height?: number | `${number}` format?: MediaFormat quality?: number | `${number}` fit?: MediaFit frameTime?: number boost?: number } export function optimize( image: string | URL, { width, height, format, quality, fit, frameTime, boost }: MediaParams, ): string { try { if (typeof image === "string") { image = new URL(image) } } catch { return image.toString() } if (!(image instanceof URL)) { return image } if (image.host === "raw2.seadn.io") { image.host = "i2.seadn.io" } const isFrameable = canExtractFrame(image) if (!(canBeResized(image) || isFrameable)) { return originalURL(image) } // for partial content stremaing if (isVideo(image) && frameTime === undefined) { return originalURL(image) } const params = new URLSearchParams() if (frameTime !== undefined) { if (isFrameable) { params.set("frame-time", String(frameTime)) } } else if (isVideo(image)) { return image.toString() } if (height !== undefined) { params.set("h", String(boostSize(height, boost))) } if (width !== undefined) { params.set("w", String(boostSize(width, boost))) } if (format !== undefined) { params.set("format", format) } if (quality) { if (Number(quality) <= 0 || Number(quality) > 100) { throw new Error("Quality has to be a positive number between 1 and 100") } params.set("q", String(quality)) } if (fit !== undefined) { params.set("fit", fit) } image.search = params.toString() return image.toString() } function isVideo(url: URL): boolean { const extension = getExtension(url) return ( extension === "mp4" || extension === "mov" || extension === "webm" || extension === "m4v" || extension === "ogg" || extension === "ogv" ) } function canExtractFrame(url: URL): boolean { return isVideo(url) || getExtension(url) === "gif" } function canBeResized(url: URL): boolean { if (!isSeadnURL(url)) { return false } const extension = getExtension(url) switch (extension) { case "jpg": case "png": case "jpeg": case "webp": case "avif": case "ico": case "bmp": case "gif": case "tiff": case "tif": case undefined: return true default: return false } } function getExtension(url: URL): string | undefined { const split = url.pathname.split(".") if (split.length <= 1) { return } return split[split.length - 1] } export function isSeadnURL(url: URL): boolean { return url.hostname.endsWith("seadn.io") } export function originalURL(image: URL | string): string { try { if (typeof image === "string") { image = new URL(image) } } catch { return image.toString() } if (!isSeadnURL(image)) { return image.toString() } image.hostname = getOriginalHostname(image) return image.toString() } export function getOriginalHostname(url: URL): string { return url.hostname.replace("i2c", "raw2").replace("i2", "raw2") }