1 | const browserslist = require('browserslist')
|
2 |
|
3 | const versionToNumber = (v) => {
|
4 | if (v === 'all') return 0
|
5 | if (v.includes('-')) v = v.slice(0, v.indexOf('-'))
|
6 | return +v
|
7 | }
|
8 |
|
9 | const 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 |
|
18 | const 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 |
|
29 | module.exports = (queries) => {
|
30 |
|
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 |
|
38 | queries = queries.map(formatBrowserNames)
|
39 |
|
40 |
|
41 |
|
42 | const minSpecified = queries.map((q) => q.reduce(getMinVersionObject, {}))
|
43 |
|
44 |
|
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 |
|
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 |
|
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 |
|
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 | }
|