Provide mappings for caniuse
cupcakearmy opened this issue · 4 comments
Would be amazing if this library could provide mappings for caniuse syntax in stats.
Example (https://github.com/Fyrd/caniuse/blob/main/features-json/webp.json)
I love caniuse, however I'm not sure what you mean by mappings?
So I was using your library yesterday and wanted to do some server side feature detection for the browser basically.
And I was wondering if it might be a nice idea to have client.caniuse
or something similar with the shorthand name of the browser that is used in the caniuse database. An example here.
Basically I need to match the browser name to the shorthand in caniuse, if that makes sense
Some poc of yesterday, what is relevant is the BrowserMappings
in this case.
import DeviceDetector from 'device-detector-js'
import Avif from 'caniuse-db/features-json/avif.json'
import WebP from 'caniuse-db/features-json/webp.json'
const detector = new DeviceDetector()
function findLowestSupportedVersion(stat: Record<string, string>): 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 parseInt(version)
}
}
return null
}
const BrowserMappings = {
'Internet Explorer': 'ie',
'Microsoft Edge': 'edge',
Firefox: 'firefox',
Chrome: 'chrome',
Safari: 'safari',
Opera: 'opera',
'Mobile Safari': 'ios_saf',
'Opera Mini': 'op_mini',
'Android Browser': 'android',
'Chrome Mobile': 'and_chr',
'Firefox Mobile': 'and_ff',
'UC Browser': 'and_uc',
'Samsung Browser': 'samsung',
'QQ Browser': 'and_qq',
}
function matchBrowserToStat(browser: DeviceDetector.DeviceDetectorResult): string {
if (browser.os!.name === 'iOS') {
return 'ios_saf'
}
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]
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
}
}
I think this is a clever use of this library but I don't like the idea of having to maintain the mappings myself. I think what you did with your POC could totally live in it's own npm package.
Understandable :)