diff --git a/src/controllers/index.ts b/src/controllers/index.ts index 584c6d4..a6d8a4b 100644 --- a/src/controllers/index.ts +++ b/src/controllers/index.ts @@ -13,16 +13,12 @@ import { RouteHandlerMethod } from 'fastify' import sharp, { FitEnum, FormatEnum } from 'sharp' import { flatten, unflatten } from 'flat' import ms from 'ms' -import DeviceDetector from 'device-detector-js' -import Avif from 'caniuse-db/features-json/avif.json' -import WebP from 'caniuse-db/features-json/webp.json' import { storage } from '../storage' import { transform } from '../transform' import { sha3, sortObjectByKeys, validateSyncOrFail } from '../utils/utils' import { Config, URLClean } from '../config' - -const detector = new DeviceDetector() +import { supportsAvif, supportsWebP } from '../utils/caniuse' export class ComplexParameter { @IsString() @@ -170,11 +166,9 @@ export class TransformQueryBase { } autoFormat(ua: string) { - const parsed = detector.parse(ua) - //https://caniuse.com/avif - console.log(parsed) - console.log(WebP) - // https://caniuse.com/webp + if (supportsAvif(ua)) this.format!.name = 'avif' + else if (supportsWebP(ua)) this.format!.name = 'webp' + else this.format!.name = 'jpeg' } } diff --git a/src/utils/caniuse.ts b/src/utils/caniuse.ts index ee4c0e6..e7b2ffc 100644 --- a/src/utils/caniuse.ts +++ b/src/utils/caniuse.ts @@ -4,16 +4,17 @@ import WebP from 'caniuse-db/features-json/webp.json' const detector = new DeviceDetector() -function findLowestCompatibleVersion(stat: Record): string { +function findLowestSupportedVersion(stat: Record): number | null { const entries = Object.entries(stat).sort((a, b) => parseInt(a[0]) - parseInt(b[0])) for (const [version, support] of entries) { if (support.startsWith('y') || support.startsWith('a')) { - return version + return parseInt(version) } } + return null } -const mapping = { +const BrowserMappings = { 'Internet Explorer': 'ie', 'Microsoft Edge': 'edge', Firefox: 'firefox', @@ -31,20 +32,40 @@ const mapping = { } function matchBrowserToStat(browser: DeviceDetector.DeviceDetectorResult): string { - if (!browser.os || !browser.client) throw new Error('Invalid browser') - if (browser.os.name === 'iOS') { + if (browser.os!.name === 'iOS') { return 'ios_saf' } - if (browser.os.name in mapping) { - return mapping[browser.os.name as keyof typeof mapping] + if (browser.client!.name in BrowserMappings) { + return BrowserMappings[browser.client!.name as keyof typeof BrowserMappings] } throw new Error('Could not determine mapping for browser') } function match(feature: typeof Avif | typeof WebP, ua: string): boolean { const browser = detector.parse(ua) + if (!browser.client || !browser.os) { + throw new Error('Could not parse browser') + } const stats = feature.stats[matchBrowserToStat(browser) as keyof typeof feature.stats] - console.debug(stats) - console.debug(findLowestCompatibleVersion(stats)) - return false + const lowestSupported = findLowestSupportedVersion(stats) + if (lowestSupported === null) { + return false + } + return lowestSupported <= parseInt(browser.client.version) +} + +export function supportsAvif(ua: string): boolean { + try { + return match(Avif, ua) + } catch { + return false + } +} + +export function supportsWebP(ua: string): boolean { + try { + return match(WebP, ua) + } catch { + return false + } }