forked from browserslist/browserslist
-
Notifications
You must be signed in to change notification settings - Fork 0
/
get-browsers.js
118 lines (97 loc) 路 2.93 KB
/
get-browsers.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import { agents as caniuseAgents, region as caniuseRegion } from 'caniuse-lite'
import { readFileSync } from 'node:fs'
import browserslist from 'browserslist'
import { URL } from 'node:url'
let { version: bv } = importJSON('../node_modules/browserslist/package.json')
let { version: cv } = importJSON('../node_modules/caniuse-lite/package.json')
export const QUERY_DEFAULTS = 'defaults'
export const REGION_GLOBAL = 'Global'
export default async function getBrowsers(query, region) {
let browsersByQuery = []
try {
browsersByQuery = browserslist(query)
} catch (error) {
throw error.browserslist
? error
: new Error(`Unknown browser query \`${query}\`.`)
}
let browsersCoverageByQuery = {}
for (let browser of browsersByQuery) {
let [id, version] = browser.split(' ')
let versionCoverage
// The Node.js is not in the Can I Use db
if (id === 'node') {
versionCoverage = null
} else {
versionCoverage = roundNumber(
region === REGION_GLOBAL
? getGlobalCoverage(id, version)
: await getRegionCoverage(id, version, region)
)
}
if (!browsersCoverageByQuery[id]) {
browsersCoverageByQuery[id] = {}
}
browsersCoverageByQuery[id][version] = versionCoverage
}
let browsers = Object.entries(browsersCoverageByQuery)
.map(([id, versions]) => {
let name
let coverage
// The Node.js is not in the Can I Use db
if (id === 'node') {
name = 'Node'
coverage = null
} else {
name = caniuseAgents[id].browser
coverage = roundNumber(
Object.values(versions).reduce((a, b) => a + b, 0)
)
}
return {
id,
name,
coverage,
versions
}
})
.sort((a, b) => b.coverage - a.coverage)
let coverage = roundNumber(browserslist.coverage(browsersByQuery, region))
return {
query,
region,
coverage,
versions: {
browserslist: bv,
caniuse: cv
},
browsers
}
}
function getGlobalCoverage(id, version) {
return getCoverage(caniuseAgents[id].usage_global, version)
}
async function getRegionCoverage(id, version, region) {
try {
if (region.includes('/')) {
throw new Error(`Invalid symbols in region name \`${region}\`.`)
}
let { default: regionData } = await import(
`caniuse-lite/data/regions/${region}.js`
)
return getCoverage(caniuseRegion(regionData)[id], version)
} catch (e) {
throw new Error(`Unknown region name \`${region}\`.`)
}
}
function getCoverage(data, version) {
let [lastVersion] = Object.keys(data).sort((a, b) => Number(b) - Number(a))
// If specific version coverage is missing, fall back to 'version zero'
return data[version] !== undefined ? data[version] : data[lastVersion]
}
function roundNumber(value) {
return Math.round(value * 100) / 100
}
function importJSON(path) {
return JSON.parse(readFileSync(new URL(path, import.meta.url)))
}