browserslist 4.3.4 → 4.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/README.md +42 -20
- package/index.js +136 -37
- package/node.js +1 -1
- package/package.json +9 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,19 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
This project adheres to [Semantic Versioning](http://semver.org/).
|
|
3
3
|
|
|
4
|
+
## 4.4
|
|
5
|
+
* Added `and` and `or` keywords to combine queries (by Jon Ege Ronnenberg).
|
|
6
|
+
|
|
7
|
+
## 4.3.7
|
|
8
|
+
* Fix fraction years support in `last 1.5 years` (by Clément P).
|
|
9
|
+
* Fix version-less browser support.
|
|
10
|
+
|
|
11
|
+
## 4.3.6
|
|
12
|
+
* Fix version-less browser support in custom statistics (by Alex Walter).
|
|
13
|
+
|
|
14
|
+
## 4.3.5
|
|
15
|
+
* Fix `not` query for wrong Can I Use data.
|
|
16
|
+
|
|
4
17
|
## 4.3.4
|
|
5
18
|
* Allow to update `node-releases` without new Browserslist releases.
|
|
6
19
|
|
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Browserslist [![Cult Of Martians][cult-img]][cult]
|
|
2
2
|
|
|
3
3
|
<img width="120" height="120" alt="Browserslist logo by Anton Lovchikov"
|
|
4
|
-
src="
|
|
4
|
+
src="https://browserslist.github.io/browserslist/logo.svg" align="right">
|
|
5
5
|
|
|
6
6
|
The config to share target browsers and Node.js versions between different
|
|
7
7
|
front-end tools. It is used in:
|
|
@@ -41,16 +41,16 @@ not dead
|
|
|
41
41
|
|
|
42
42
|
Developers set versions list in queries like `last 2 version`
|
|
43
43
|
to be free from updating versions manually.
|
|
44
|
-
Browserslist will
|
|
44
|
+
Browserslist will use [Can I Use] data for this queries.
|
|
45
45
|
|
|
46
46
|
Browserslist will take queries from tool option,
|
|
47
47
|
`browserslist` config, `.browserslistrc` config,
|
|
48
|
-
`browserslist` section in
|
|
48
|
+
`browserslist` section in `package.json` or environment variables.
|
|
49
49
|
|
|
50
50
|
You can test Browserslist queries in [online demo].
|
|
51
51
|
|
|
52
|
-
[cult-img]:
|
|
53
|
-
[cult]:
|
|
52
|
+
[cult-img]: https://cultofmartians.com/assets/badges/badge.svg
|
|
53
|
+
[cult]: https://cultofmartians.com/done.html
|
|
54
54
|
|
|
55
55
|
<a href="https://evilmartians.com/?utm_source=browserslist">
|
|
56
56
|
<img src="https://evilmartians.com/badges/sponsored-by-evil-martians.svg"
|
|
@@ -59,13 +59,13 @@ You can test Browserslist queries in [online demo].
|
|
|
59
59
|
|
|
60
60
|
[stylelint-no-unsupported-browser-features]: https://github.com/ismay/stylelint-no-unsupported-browser-features
|
|
61
61
|
[eslint-plugin-compat]: https://github.com/amilajack/eslint-plugin-compat
|
|
62
|
-
[Browserslist Example]:
|
|
62
|
+
[Browserslist Example]: https://github.com/browserslist/browserslist-example
|
|
63
63
|
[postcss-preset-env]: https://github.com/jonathantneal/postcss-preset-env
|
|
64
64
|
[postcss-normalize]: https://github.com/jonathantneal/postcss-normalize
|
|
65
65
|
[Autoprefixer]: https://github.com/postcss/autoprefixer
|
|
66
|
-
[online demo]:
|
|
67
|
-
[Can I Use]:
|
|
68
|
-
[Babel]:
|
|
66
|
+
[online demo]: https://browserl.ist/
|
|
67
|
+
[Can I Use]: https://caniuse.com/
|
|
68
|
+
[Babel]: https://github.com/babel/babel/tree/master/packages/babel-preset-env
|
|
69
69
|
|
|
70
70
|
## Tools
|
|
71
71
|
|
|
@@ -102,18 +102,43 @@ from one of this sources:
|
|
|
102
102
|
`> 0.5%, last 2 versions, Firefox ESR, not dead`.
|
|
103
103
|
|
|
104
104
|
|
|
105
|
+
### Query Composition
|
|
106
|
+
|
|
107
|
+
An `or` combiner can use the keyword `or` as well as `,`.
|
|
108
|
+
`last 1 version or > 1%` is equal to `last 1 version, > 1%`.
|
|
109
|
+
|
|
110
|
+
`and` query combinations are also supported to perform an
|
|
111
|
+
intersection of the previous query: `last 1 version and > 1%`.
|
|
112
|
+
|
|
113
|
+
There is 3 different ways to combine queries as depicted below. First you start
|
|
114
|
+
with a single query and then we combine the queries to get our final list.
|
|
115
|
+
|
|
116
|
+
Obviously you can *not* start with a `not` combiner, since the is no left-hand
|
|
117
|
+
side query to combine it with.
|
|
118
|
+
|
|
119
|
+
| Query combiner type | Illustration | Example |
|
|
120
|
+
| ------------------- | :----------: | ------- |
|
|
121
|
+
|`or`/ `,` combiner <br> (union) |  | `'> .5% or last 2 versions'` <br> `'> .5%, last 2 versions'` |
|
|
122
|
+
| `and` combiner <br> (intersection) |  | `'> .5% and last 2 versions'` |
|
|
123
|
+
| `not` combiner <br> (relative complement) |  | `'> .5% and not last 2 versions'` <br> `'> .5% or not last 2 versions'` <br> `'> .5%, not last 2 versions'` |
|
|
124
|
+
|
|
125
|
+
_A quick way to test your query is to do `npx browserslist '> 0.5%, not IE 11'`
|
|
126
|
+
in your terminal._
|
|
127
|
+
|
|
128
|
+
|
|
105
129
|
### Best Practices
|
|
106
130
|
|
|
107
131
|
* Select browsers directly (`last 2 Chrome versions`) only if you are making
|
|
108
|
-
a web app for a kiosk with one browser. There
|
|
132
|
+
a web app for a kiosk with one browser. There are a lot of browsers
|
|
109
133
|
on the market. If you are making general web app you should respect
|
|
110
134
|
browsers diversity.
|
|
111
135
|
* If you want to change the default set of browsers we recommend to combine
|
|
112
|
-
`last 1 version`, `not dead` with `> 0.2%` (or
|
|
136
|
+
`last 1 version`, `not dead` with `> 0.2%` (or `> 1% in US`,
|
|
113
137
|
`> 1% in my stats`). `last n versions` adds too many dead browsers
|
|
114
|
-
and does not add popular old versions.
|
|
115
|
-
|
|
116
|
-
as we had with Internet Explorer 6.
|
|
138
|
+
and does not add popular old versions. Choosing a percentage above `0.2%`
|
|
139
|
+
will in the long run make popular browsers even more popular. We might run
|
|
140
|
+
into a monopoly and stagnation situation, as we had with Internet Explorer 6.
|
|
141
|
+
Please use this setting with caution.
|
|
117
142
|
* Don’t remove browsers just because you don’t know them. Opera Mini has
|
|
118
143
|
100 million users in Africa and it is more popular in the global market
|
|
119
144
|
than Microsoft Edge. Chinese QQ Browsers has more market share than Firefox
|
|
@@ -193,18 +218,15 @@ samsung 5
|
|
|
193
218
|
Browserslist works with separated versions of browsers.
|
|
194
219
|
You should avoid queries like `Firefox > 0`.
|
|
195
220
|
|
|
196
|
-
Multiple criteria are combined as a boolean `OR`. A browser version must match
|
|
197
|
-
at least one of the criteria to be selected.
|
|
198
|
-
|
|
199
221
|
All queries are based on the [Can I Use] support table,
|
|
200
222
|
e.g. `last 3 iOS versions` might select `8.4, 9.2, 9.3` (mixed major and minor),
|
|
201
223
|
whereas `last 3 Chrome versions` might select `50, 49, 48` (major only).
|
|
202
224
|
|
|
203
225
|
[`caniuse-lite/data/regions`]: https://github.com/ben-eb/caniuse-lite/tree/master/data/regions
|
|
204
|
-
[two-letter country code]:
|
|
226
|
+
[two-letter country code]: https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements
|
|
205
227
|
[custom usage data]: #custom-usage-data
|
|
206
228
|
[still maintained]: https://github.com/nodejs/Release
|
|
207
|
-
[Can I Use]:
|
|
229
|
+
[Can I Use]: https://caniuse.com/
|
|
208
230
|
|
|
209
231
|
|
|
210
232
|
### Browsers
|
|
@@ -424,7 +446,7 @@ while also querying against global or regional data.
|
|
|
424
446
|
For example, the query `> 1% in my stats, > 5% in US, 10%` is permitted.
|
|
425
447
|
|
|
426
448
|
[`browserslist-ga`]: https://github.com/browserslist/browserslist-ga
|
|
427
|
-
[Can I Use]:
|
|
449
|
+
[Can I Use]: https://caniuse.com/
|
|
428
450
|
|
|
429
451
|
|
|
430
452
|
## JS API
|
package/index.js
CHANGED
|
@@ -8,6 +8,13 @@ var BrowserslistError = require('./error')
|
|
|
8
8
|
var env = require('./node') // Will load browser.js in webpack
|
|
9
9
|
|
|
10
10
|
var FLOAT_RANGE = /^\d+(\.\d+)?(-\d+(\.\d+)?)*$/
|
|
11
|
+
var YEAR = 365.259641 * 24 * 60 * 60 * 1000
|
|
12
|
+
|
|
13
|
+
// Enum values MUST be powers of 2, so combination are safe
|
|
14
|
+
/** @constant {number} */
|
|
15
|
+
var QUERY_OR = 1
|
|
16
|
+
/** @constant {number} */
|
|
17
|
+
var QUERY_AND = 2
|
|
11
18
|
|
|
12
19
|
function isVersionsMatch (versionA, versionB) {
|
|
13
20
|
return (versionA + '.').indexOf(versionB + '.') === 0
|
|
@@ -103,6 +110,7 @@ function normalizeVersion (data, version) {
|
|
|
103
110
|
}
|
|
104
111
|
|
|
105
112
|
function filterByYear (since) {
|
|
113
|
+
since = since / 1000
|
|
106
114
|
return Object.keys(agents).reduce(function (selected, name) {
|
|
107
115
|
var data = byName(name)
|
|
108
116
|
if (!data) return selected
|
|
@@ -132,10 +140,23 @@ function unknownQuery (query) {
|
|
|
132
140
|
)
|
|
133
141
|
}
|
|
134
142
|
|
|
143
|
+
/**
|
|
144
|
+
* Resolves queries into a browser list.
|
|
145
|
+
* @param {string|string[]} queries Queries to combine.
|
|
146
|
+
* Either an array of queries or a long string of queries.
|
|
147
|
+
* @param {object} [context] Optional arguments to
|
|
148
|
+
* the select function in `queries`.
|
|
149
|
+
* @returns {string[]} A list of browsers
|
|
150
|
+
*/
|
|
135
151
|
function resolve (queries, context) {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
152
|
+
if (Array.isArray(queries)) {
|
|
153
|
+
queries = flatten(queries.map(parse))
|
|
154
|
+
} else {
|
|
155
|
+
queries = parse(queries)
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
return queries.reduce(function (result, query, index) {
|
|
159
|
+
var selection = query.queryString
|
|
139
160
|
|
|
140
161
|
var isExclude = selection.indexOf('not ') === 0
|
|
141
162
|
if (isExclude) {
|
|
@@ -152,16 +173,44 @@ function resolve (queries, context) {
|
|
|
152
173
|
var match = selection.match(type.regexp)
|
|
153
174
|
if (match) {
|
|
154
175
|
var args = [context].concat(match.slice(1))
|
|
155
|
-
var array = type.select.apply(browserslist, args)
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
return
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
176
|
+
var array = type.select.apply(browserslist, args).map(function (j) {
|
|
177
|
+
var parts = j.split(' ')
|
|
178
|
+
if (parts[1] === '0') {
|
|
179
|
+
return parts[0] + ' ' + byName(parts[0]).versions[0]
|
|
180
|
+
} else {
|
|
181
|
+
return j
|
|
182
|
+
}
|
|
183
|
+
})
|
|
184
|
+
|
|
185
|
+
switch (query.type) {
|
|
186
|
+
case QUERY_AND:
|
|
187
|
+
if (isExclude) {
|
|
188
|
+
return result.filter(function (j) {
|
|
189
|
+
// remove result items that are in array
|
|
190
|
+
// (the relative complement of array in result)
|
|
191
|
+
return array.indexOf(j) === -1
|
|
192
|
+
})
|
|
193
|
+
} else {
|
|
194
|
+
return result.filter(function (j) {
|
|
195
|
+
// remove result items not in array
|
|
196
|
+
// (intersect of result and array)
|
|
197
|
+
return array.indexOf(j) !== -1
|
|
198
|
+
})
|
|
199
|
+
}
|
|
200
|
+
case QUERY_OR:
|
|
201
|
+
default:
|
|
202
|
+
if (isExclude) {
|
|
203
|
+
var filter = { }
|
|
204
|
+
array.forEach(function (j) {
|
|
205
|
+
filter[j] = true
|
|
206
|
+
})
|
|
207
|
+
return result.filter(function (j) {
|
|
208
|
+
return !filter[j]
|
|
209
|
+
})
|
|
210
|
+
}
|
|
211
|
+
// union of result and array
|
|
212
|
+
return result.concat(array)
|
|
163
213
|
}
|
|
164
|
-
return result.concat(array)
|
|
165
214
|
}
|
|
166
215
|
}
|
|
167
216
|
|
|
@@ -186,7 +235,7 @@ function resolve (queries, context) {
|
|
|
186
235
|
* version in direct query.
|
|
187
236
|
* @param {boolean} [opts.dangerousExtend] Disable security checks
|
|
188
237
|
* for extend query.
|
|
189
|
-
* @
|
|
238
|
+
* @returns {string[]} Array with browser names in Can I Use.
|
|
190
239
|
*
|
|
191
240
|
* @example
|
|
192
241
|
* browserslist('IE >= 10, IE 8') //=> ['ie 11', 'ie 10', 'ie 8']
|
|
@@ -207,13 +256,9 @@ function browserslist (queries, opts) {
|
|
|
207
256
|
}
|
|
208
257
|
}
|
|
209
258
|
|
|
210
|
-
if (typeof queries === 'string') {
|
|
211
|
-
queries = queries.split(/,\s*/)
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
if (!Array.isArray(queries)) {
|
|
259
|
+
if (!(typeof queries === 'string' || Array.isArray(queries))) {
|
|
215
260
|
throw new BrowserslistError(
|
|
216
|
-
'Browser queries must be an array. Got ' + typeof queries + '.')
|
|
261
|
+
'Browser queries must be an array or string. Got ' + typeof queries + '.')
|
|
217
262
|
}
|
|
218
263
|
|
|
219
264
|
var context = {
|
|
@@ -230,16 +275,7 @@ function browserslist (queries, opts) {
|
|
|
230
275
|
}
|
|
231
276
|
}
|
|
232
277
|
|
|
233
|
-
var result = resolve(queries, context).
|
|
234
|
-
var parts = i.split(' ')
|
|
235
|
-
var name = parts[0]
|
|
236
|
-
var version = parts[1]
|
|
237
|
-
if (version === '0') {
|
|
238
|
-
return name + ' ' + byName(name).versions[0]
|
|
239
|
-
} else {
|
|
240
|
-
return i
|
|
241
|
-
}
|
|
242
|
-
}).sort(function (name1, name2) {
|
|
278
|
+
var result = resolve(queries, context).sort(function (name1, name2) {
|
|
243
279
|
name1 = name1.split(' ')
|
|
244
280
|
name2 = name2.split(' ')
|
|
245
281
|
if (name1[0] === name2[0]) {
|
|
@@ -256,6 +292,74 @@ function browserslist (queries, opts) {
|
|
|
256
292
|
return uniq(result)
|
|
257
293
|
}
|
|
258
294
|
|
|
295
|
+
/**
|
|
296
|
+
* @typedef {object} BrowserslistQuery
|
|
297
|
+
* @property {number} type A type constant like QUERY_OR @see QUERY_OR.
|
|
298
|
+
* @property {string} queryString A query like "not ie < 11".
|
|
299
|
+
*/
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Parse a browserslist string query
|
|
303
|
+
* @param {string} queries One or more queries as a string
|
|
304
|
+
* @returns {BrowserslistQuery[]} An array of BrowserslistQuery
|
|
305
|
+
*/
|
|
306
|
+
function parse (queries) {
|
|
307
|
+
var qs = []
|
|
308
|
+
|
|
309
|
+
do {
|
|
310
|
+
queries = doMatch(queries, qs)
|
|
311
|
+
} while (queries)
|
|
312
|
+
|
|
313
|
+
return qs
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Find query matches in a string. This function is meant to be called
|
|
318
|
+
* repeatedly with the returned query string until there is no more matches.
|
|
319
|
+
* @param {string} string A string with one or more queries.
|
|
320
|
+
* @param {BrowserslistQuery[]} qs Out parameter,
|
|
321
|
+
* will be filled with `BrowserslistQuery`.
|
|
322
|
+
* @returns {string} The rest of the query string minus the matched part.
|
|
323
|
+
*/
|
|
324
|
+
function doMatch (string, qs) {
|
|
325
|
+
var or = /^(?:,\s*|\s+OR\s+)(.*)/i
|
|
326
|
+
var and = /^\s+AND\s+(.*)/i
|
|
327
|
+
|
|
328
|
+
return find(
|
|
329
|
+
string,
|
|
330
|
+
function (parsed, n, max) {
|
|
331
|
+
if (and.test(parsed)) {
|
|
332
|
+
qs.unshift({ type: QUERY_AND, queryString: parsed.match(and)[1] })
|
|
333
|
+
return true
|
|
334
|
+
} else if (or.test(parsed)) {
|
|
335
|
+
qs.unshift({ type: QUERY_OR, queryString: parsed.match(or)[1] })
|
|
336
|
+
return true
|
|
337
|
+
} else if (n === max) {
|
|
338
|
+
qs.unshift({ type: QUERY_OR, queryString: parsed.trim() })
|
|
339
|
+
return true
|
|
340
|
+
}
|
|
341
|
+
return false
|
|
342
|
+
}
|
|
343
|
+
)
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
function find (string, predicate) {
|
|
347
|
+
for (var n = 1, max = string.length; n <= max; n++) {
|
|
348
|
+
var parsed = string.substr(-n, n)
|
|
349
|
+
if (predicate(parsed, n, max)) {
|
|
350
|
+
return string.replace(parsed, '')
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
return ''
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
function flatten (array) {
|
|
357
|
+
if (!Array.isArray(array)) return [array]
|
|
358
|
+
return array.reduce(function (a, b) {
|
|
359
|
+
return a.concat(flatten(b))
|
|
360
|
+
}, [])
|
|
361
|
+
}
|
|
362
|
+
|
|
259
363
|
// Will be filled by Can I Use data below
|
|
260
364
|
browserslist.data = { }
|
|
261
365
|
browserslist.usage = {
|
|
@@ -444,12 +548,9 @@ var QUERIES = [
|
|
|
444
548
|
}
|
|
445
549
|
},
|
|
446
550
|
{
|
|
447
|
-
regexp: /^last\s+(\d+)\s+years?$/i,
|
|
551
|
+
regexp: /^last\s+(\d*.?\d+)\s+years?$/i,
|
|
448
552
|
select: function (context, years) {
|
|
449
|
-
|
|
450
|
-
var since = date.setFullYear(date.getFullYear() - years) / 1000
|
|
451
|
-
|
|
452
|
-
return filterByYear(since)
|
|
553
|
+
return filterByYear(Date.now() - YEAR * years)
|
|
453
554
|
}
|
|
454
555
|
},
|
|
455
556
|
{
|
|
@@ -458,9 +559,7 @@ var QUERIES = [
|
|
|
458
559
|
year = parseInt(year)
|
|
459
560
|
month = parseInt(month || '01') - 1
|
|
460
561
|
date = parseInt(date || '01')
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
return filterByYear(since)
|
|
562
|
+
return filterByYear(Date.UTC(year, month, date, 0, 0, 0))
|
|
464
563
|
}
|
|
465
564
|
},
|
|
466
565
|
{
|
package/node.js
CHANGED
|
@@ -156,7 +156,7 @@ module.exports = {
|
|
|
156
156
|
if (versions.length === 1 && data[i] && data[i].versions.length === 1) {
|
|
157
157
|
var normal = Object.keys(data[i].versions)[0]
|
|
158
158
|
normalized[i] = { }
|
|
159
|
-
normalized[i][normal] = stats[i]
|
|
159
|
+
normalized[i][normal] = stats[i][versions[0]]
|
|
160
160
|
} else {
|
|
161
161
|
normalized[i] = stats[i]
|
|
162
162
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "browserslist",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.4.0",
|
|
4
4
|
"description": "Share target browsers between different front-end tools, like Autoprefixer, Stylelint and babel-env-preset",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"caniuse",
|
|
@@ -11,13 +11,18 @@
|
|
|
11
11
|
"license": "MIT",
|
|
12
12
|
"repository": "browserslist/browserslist",
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"caniuse-lite": "^1.0.
|
|
15
|
-
"electron-to-chromium": "^1.3.
|
|
16
|
-
"node-releases": "^1.
|
|
14
|
+
"caniuse-lite": "^1.0.30000928",
|
|
15
|
+
"electron-to-chromium": "^1.3.100",
|
|
16
|
+
"node-releases": "^1.1.3"
|
|
17
17
|
},
|
|
18
18
|
"bin": "./cli.js",
|
|
19
19
|
"browser": {
|
|
20
20
|
"./node.js": "./browser.js",
|
|
21
21
|
"path": false
|
|
22
|
+
},
|
|
23
|
+
"husky": {
|
|
24
|
+
"hooks": {
|
|
25
|
+
"pre-commit": "lint-staged"
|
|
26
|
+
}
|
|
22
27
|
}
|
|
23
28
|
}
|