UNPKG

2.68 kBJavaScriptView Raw
1const browserslist = require('browserslist')
2
3const versionToNumber = (v) => {
4 if (v === 'all') return 0
5 if (v.includes('-')) v = v.slice(0, v.indexOf('-'))
6 return +v
7}
8
9const formatBrowserNames = (q) => {
10 return q.map((entry) => {
11 return entry.replace(/(^[a-z_]+)(\s*[><=])/i, (a, b, c) => {
12 b = browserslist(`last 1 ${b} version`)[0].split(' ')[0]
13 return b + c
14 })
15 })
16}
17
18const getMinVersionObject = (obj, entry) => {
19 if (/^[a-z_]+\s*>=/i.test(entry)) {
20 let browser, version
21 [browser, version] = entry.split(/\s*>=+\s*/)
22 version = versionToNumber(version.trim())
23 browser = browser.trim()
24 if (!obj[browser] || obj[browser > version]) obj[browser] = version
25 }
26 return obj
27}
28
29module.exports = (queries) => {
30 // convert any string queries to arrays
31 queries = queries.map((q) => {
32 if (Array.isArray(q)) return q
33 q = q.split(/\s*,\s*/)
34 return Array.isArray(q) ? q : [q]
35 })
36
37 // format browser names consistently
38 queries = queries.map(formatBrowserNames)
39
40 // get minimum version object for specified version in eah query
41 // this is to protect against caniuse db not containing full list of versions
42 const minSpecified = queries.map((q) => q.reduce(getMinVersionObject, {}))
43
44 // generate a list of unique browsers for each query
45 const supported = queries.map((q, index) => {
46 return browserslist(q).reduce((list, browser) => {
47 let version
48 [browser, version] = browser.split(' ')
49 version = versionToNumber(version)
50 if (!list[browser] || list[browser] > version) list[browser] = version
51 if (minSpecified[index][browser] && list[browser] > minSpecified[index][browser]) list[browser] = minSpecified[index][browser]
52 return list
53 }, {})
54 })
55
56 // count # occurences of each browser throughout each list for filtering
57 const browserCount = supported.reduce((browsers, list) => {
58 Object.keys(list).forEach((browser) => {
59 if (!browsers[browser]) browsers[browser] = 0
60 browsers[browser]++
61 })
62 return browsers
63 }, {})
64
65 // generate a consolidated minimum supported browser list
66 const minSupported = supported.reduce((min, list) => {
67 Object.keys(list).filter((browser) => browserCount[browser] === supported.length)
68 .forEach((browser) => {
69 if (!min[browser] || min[browser] < list[browser]) min[browser] = list[browser]
70 })
71 return min
72 }, {})
73
74 // convert the list of supported browsers back into a browserslist query
75 const query = Object.keys(minSupported).map((browser) => {
76 if (minSupported[browser] === 0) return `${browser} all`
77 return `${browser} >= ${minSupported[browser]}`
78 })
79
80 return query
81}