browserslist 4.11.1 → 4.13.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 CHANGED
@@ -1,8 +1,23 @@
1
1
  # Change Log
2
2
  This project adheres to [Semantic Versioning](http://semver.org/).
3
3
 
4
+ ## 4.13
5
+ * Added `supports` query to select browsers (by Jesús Leganés-Combarro).
6
+
7
+ ## 4.12.2
8
+ * Update Firefox ESR.
9
+
10
+ ## 4.12.1
11
+ * Update `package.json` scanning tool for `--update-db` (by Luke Edwards).
12
+ * Improve docs (by Mukundan Senthil).
13
+ * Drop Node.js 13.0-13.6 support because of ES modules bug in that versions.
14
+
15
+ ## 4.12
16
+ * Add environments to shared configs (by Yevgeny Petukhov).
17
+ * Fix docs (by Dmitry Statsenko and Thomas Pozzo di Borgo).
18
+
4
19
  ## 4.11.1
5
- * FIx Node.js 6 support.
20
+ * Fix Node.js 6 support.
6
21
 
7
22
  ## 4.11
8
23
  * Add `npx browserslist --mobile-to-desktop` (by James Ross).
package/README.md CHANGED
@@ -17,12 +17,12 @@ front-end tools. It is used in:
17
17
  All tools will find target browsers automatically,
18
18
  when you add the following to `package.json`:
19
19
 
20
- ```js
20
+ ```json
21
21
  "browserslist": [
22
22
  "defaults",
23
23
  "not IE 11",
24
24
  "not IE_Mob 11",
25
- "maintained node versions",
25
+ "maintained node versions"
26
26
  ]
27
27
  ```
28
28
 
@@ -68,16 +68,24 @@ Browserslist will take queries from tool option,
68
68
 
69
69
  ## Table of Contents
70
70
 
71
- 1. [Tools](#tools)
72
- 2. [Best Practices](#best-practices)
73
- 3. [Queries](#queries)
74
- 4. [Config File](#config-file)
75
- 5. [Shareable Configs](#shareable-configs)
76
- 6. [Configuring for Different Environments](#configuring-for-different-environments)
77
- 7. [Custom Usage Data](#custom-usage-data)
78
- 8. [JS API](#js-api)
79
- 9. [Environment Variables](#environment-variables)
80
- 10. [Cache](#cache)
71
+ * [Tools](#tools)
72
+ * [Best Practices](#best-practices)
73
+ * [Queries](#queries)
74
+ * [Query Composition](#query-composition)
75
+ * [Full List](#full-list)
76
+ * [Debug](#debug)
77
+ * [Browsers](#browsers)
78
+ * [Config File](#config-file)
79
+ * [`package.json`](#packagejson)
80
+ * [`.browserslistrc`](#browserslistrc)
81
+ * [Shareable Configs](#shareable-configs)
82
+ * [Configuring for Different Environments](#configuring-for-different-environments)
83
+ * [Custom Usage Data](#custom-usage-data)
84
+ * [JS API](#js-api)
85
+ * [Environment Variables](#environment-variables)
86
+ * [Cache](#cache)
87
+ * [Security Contact](#security-contact)
88
+ * [For Enterprise](#for-enterprise)
81
89
 
82
90
  ## Tools
83
91
 
@@ -162,18 +170,20 @@ There is 3 different ways to combine queries as depicted below. First you start
162
170
  with a single query and then we combine the queries to get our final list.
163
171
 
164
172
  Obviously you can *not* start with a `not` combiner, since there is no left-hand
165
- side query to combine it with.
173
+ side query to combine it with. The left-hand is always resolved as `and`
174
+ combiner even if `or` is used (this is an API implementation specificity).
175
+
176
+ `and` combiner has precedence over `or` combiner.
166
177
 
167
178
  | Query combiner type | Illustration | Example |
168
179
  | ------------------- | :----------: | ------- |
169
180
  |`or`/`,` combiner <br> (union) | ![Union of queries](img/union.svg) | `> .5% or last 2 versions` <br> `> .5%, last 2 versions` |
170
181
  | `and` combiner <br> (intersection) | ![intersection of queries](img/intersection.svg) | `> .5% and last 2 versions` |
171
- | `not` combiner <br> (relative complement) | ![Relative complement of queries](img/complement.svg) | `> .5% and not last 2 versions` <br> `> .5% or not last 2 versions` <br> `> .5%, not last 2 versions` |
182
+ | `not` combiner <br> (relative complement) | ![Relative complement of queries](img/complement.svg) | All those three are equivalent to the first one <br> `> .5% and not last 2 versions` <br> `> .5% or not last 2 versions` <br> `> .5%, not last 2 versions` |
172
183
 
173
184
  _A quick way to test your query is to do `npx browserslist '> 0.5%, not IE 11'`
174
185
  in your terminal._
175
186
 
176
-
177
187
  ### Full List
178
188
 
179
189
  You can specify the browser and Node.js versions by queries (case insensitive):
@@ -182,45 +192,51 @@ You can specify the browser and Node.js versions by queries (case insensitive):
182
192
  (`> 0.5%, last 2 versions, Firefox ESR, not dead`).
183
193
  * `> 5%`: browsers versions selected by global usage statistics.
184
194
  `>=`, `<` and `<=` work too.
185
- * `> 5% in US`: uses USA usage statistics. It accepts [two-letter country code].
186
- * `> 5% in alt-AS`: uses Asia region usage statistics. List of all region codes
187
- can be found at [`caniuse-lite/data/regions`].
188
- * `> 5% in my stats`: uses [custom usage data].
189
- * `> 5% in browserslist-config-mycompany stats`: uses [custom usage data]
190
- from `browserslist-config-mycompany/browserslist-stats.json`.
191
- * `cover 99.5%`: most popular browsers that provide coverage.
192
- * `cover 99.5% in US`: same as above, with [two-letter country code].
193
- * `cover 99.5% in my stats`: uses [custom usage data].
194
- * `maintained node versions`: all Node.js versions, which are [still maintained]
195
- by Node.js Foundation.
195
+ * `> 5% in US`: uses USA usage statistics.
196
+ It accepts [two-letter country code].
197
+ * `> 5% in alt-AS`: uses Asia region usage statistics.
198
+ List of all region codes can be found at [`caniuse-lite/data/regions`].
199
+ * `> 5% in my stats`: uses [custom usage data].
200
+ * `> 5% in browserslist-config-mycompany stats`: uses [custom usage data]
201
+ from `browserslist-config-mycompany/browserslist-stats.json`.
202
+ * `cover 99.5%`: most popular browsers that provide coverage.
203
+ * `cover 99.5% in US`: same as above, with [two-letter country code].
204
+ * `cover 99.5% in my stats`: uses [custom usage data].
205
+ * `dead`: browsers without official support or updates for 24 months.
206
+ Right now it is `IE 10`, `IE_Mob 11`, `BlackBerry 10`, `BlackBerry 7`,
207
+ `Samsung 4` and `OperaMobile 12.1`.
208
+ * `last 2 versions`: the last 2 versions for *each* browser.
209
+ * `last 2 Chrome versions`: the last 2 versions of Chrome browser.
210
+ * `last 2 major versions` or `last 2 iOS major versions`:
211
+ all minor/patch releases of last 2 major versions.
196
212
  * `node 10` and `node 10.4`: selects latest Node.js `10.x.x`
197
213
  or `10.4.x` release.
198
- * `current node`: Node.js version used by Browserslist right now.
214
+ * `current node`: Node.js version used by Browserslist right now.
215
+ * `maintained node versions`: all Node.js versions, which are [still maintained]
216
+ by Node.js Foundation.
217
+ * `iOS 7`: the iOS browser version 7 directly.
218
+ * `Firefox > 20`: versions of Firefox newer than 20.
219
+ `>=`, `<` and `<=` work too. It also works with Node.js.
220
+ * `ie 6-8`: selects an inclusive range of versions.
221
+ * `Firefox ESR`: the latest [Firefox ESR] version.
222
+ * `PhantomJS 2.1` and `PhantomJS 1.9`: selects Safari versions similar
223
+ to PhantomJS runtime.
199
224
  * `extends browserslist-config-mycompany`: take queries from
200
225
  `browserslist-config-mycompany` npm package.
201
- * `ie 6-8`: selects an inclusive range of versions.
202
- * `Firefox > 20`: versions of Firefox newer than 20.
203
- `>=`, `<` and `<=` work too. It also works with Node.js.
204
- * `iOS 7`: the iOS browser version 7 directly.
205
- * `Firefox ESR`: the latest [Firefox ESR] version.
206
- * `PhantomJS 2.1` and `PhantomJS 1.9`: selects Safari versions similar
207
- to PhantomJS runtime.
208
- * `unreleased versions` or `unreleased Chrome versions`:
209
- alpha and beta versions.
210
- * `last 2 major versions` or `last 2 iOS major versions`:
211
- all minor/patch releases of last 2 major versions.
226
+ * `supports rtcpeerconnection`: browsers with support for specific features.
227
+ `rtcpeerconnection` here is the `feat` parameter at the URL of the [Can I Use]
228
+ page. A list of all available features can be found at
229
+ [`caniuse-lite/data/features`].
212
230
  * `since 2015` or `last 2 years`: all versions released since year 2015
213
231
  (also `since 2015-03` and `since 2015-03-10`).
214
- * `dead`: browsers without official support or updates for 24 months.
215
- Right now it is `IE 10`, `IE_Mob 10`, `BlackBerry 10`, `BlackBerry 7`,
216
- `Samsung 4` and `OperaMobile 12.1`.
217
- * `last 2 versions`: the last 2 versions for *each* browser.
218
- * `last 2 Chrome versions`: the last 2 versions of Chrome browser.
232
+ * `unreleased versions` or `unreleased Chrome versions`:
233
+ alpha and beta versions.
219
234
  * `not ie <= 8`: exclude browsers selected by previous queries.
220
235
 
221
236
  You can add `not ` to any query.
222
237
 
223
238
  [`caniuse-lite/data/regions`]: https://github.com/ben-eb/caniuse-lite/tree/master/data/regions
239
+ [`caniuse-lite/data/features`]: https://github.com/ben-eb/caniuse-lite/tree/master/data/features
224
240
  [two-letter country code]: https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements
225
241
  [custom usage data]: #custom-usage-data
226
242
  [still maintained]: https://github.com/nodejs/Release
@@ -303,7 +319,8 @@ browsers in `package.json` with `browserslist` key:
303
319
  ### `.browserslistrc`
304
320
 
305
321
  Separated Browserslist config should be named `.browserslistrc`
306
- and have browsers queries split by a new line. Comments starts with `#` symbol:
322
+ and have browsers queries split by a new line.
323
+ Each line is combined with the `or` combiner. Comments starts with `#` symbol:
307
324
 
308
325
  ```yaml
309
326
  # Browsers that we support
@@ -365,8 +382,25 @@ module.exports = [
365
382
  ```
366
383
 
367
384
  You can also include a `browserslist-stats.json` file as part of your shareable
368
- config at the root and query it using `> 5% in browserslist-config-mycompany stats`.
369
- It uses the same format as `extends` and the `dangerousExtend` property as above.
385
+ config at the root and query it using
386
+ `> 5% in browserslist-config-mycompany stats`. It uses the same format
387
+ as `extends` and the `dangerousExtend` property as above.
388
+
389
+ You can export configs for different environments and select environment
390
+ by `BROWSERSLIST_ENV` or `env` option in your tool:
391
+
392
+ ```js
393
+ module.exports = {
394
+ development: [
395
+ 'last 1 version'
396
+ ],
397
+ production: [
398
+ 'last 1 version',
399
+ '> 1%',
400
+ 'ie 10'
401
+ ]
402
+ }
403
+ ```
370
404
 
371
405
 
372
406
  ## Configuring for Different Environments
@@ -598,3 +632,14 @@ To report a security vulnerability, please use the [Tidelift security contact].
598
632
  Tidelift will coordinate the fix and disclosure.
599
633
 
600
634
  [Tidelift security contact]: https://tidelift.com/security
635
+
636
+
637
+ ## For Enterprise
638
+
639
+ Available as part of the Tidelift Subscription.
640
+
641
+ The maintainers of `browserslist` and thousands of other packages are working
642
+ with Tidelift to deliver commercial support and maintenance for the open source
643
+ dependencies you use to build your applications. Save time, reduce risk,
644
+ and improve code health, while paying the maintainers of the exact dependencies
645
+ you use. [Learn more.](https://tidelift.com/subscription/pkg/npm-browserslist?utm_source=npm-browserslist&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)
package/browser.js CHANGED
@@ -21,10 +21,15 @@ module.exports = {
21
21
 
22
22
  loadCountry: function loadCountry () {
23
23
  throw new BrowserslistError(
24
- 'Country statistics is not supported ' +
24
+ 'Country statistics are not supported ' +
25
25
  'in client-side build of Browserslist')
26
26
  },
27
27
 
28
+ loadFeature: function loadFeature () {
29
+ throw new BrowserslistError(
30
+ 'Supports queries are not available in client-side build of Browserslist')
31
+ },
32
+
28
33
  currentNode: function currentNode (resolve, context) {
29
34
  return resolve(['maintained node versions'], context)[0]
30
35
  },
package/index.js CHANGED
@@ -424,7 +424,8 @@ function browserslist (queries, opts) {
424
424
  var context = {
425
425
  ignoreUnknownVersions: opts.ignoreUnknownVersions,
426
426
  dangerousExtend: opts.dangerousExtend,
427
- mobileToDesktop: opts.mobileToDesktop
427
+ mobileToDesktop: opts.mobileToDesktop,
428
+ env: opts.env
428
429
  }
429
430
 
430
431
  env.oldDataWarning(browserslist.data)
@@ -504,6 +505,7 @@ function flatten (array) {
504
505
  }
505
506
 
506
507
  // Will be filled by Can I Use data below
508
+ browserslist.cache = { }
507
509
  browserslist.data = { }
508
510
  browserslist.usage = {
509
511
  global: { },
@@ -645,7 +647,7 @@ var QUERIES = [
645
647
  {
646
648
  regexp: /^last\s+(\d+)\s+electron\s+major\s+versions?$/i,
647
649
  select: function (context, versions) {
648
- var validVersions = getMajorVersions(Object.keys(e2c).reverse(), versions)
650
+ var validVersions = getMajorVersions(Object.keys(e2c), versions)
649
651
  return validVersions.map(function (i) {
650
652
  return 'chrome ' + e2c[i]
651
653
  })
@@ -886,6 +888,20 @@ var QUERIES = [
886
888
  return result
887
889
  }
888
890
  },
891
+ {
892
+ regexp: /^supports\s+([\w-]+)$/,
893
+ select: function (context, feature) {
894
+ env.loadFeature(browserslist.cache, feature)
895
+ var features = browserslist.cache[feature]
896
+ return Object.keys(features).reduce(function (result, version) {
897
+ var flags = features[version]
898
+ if (flags.indexOf('y') >= 0 || flags.indexOf('a') >= 0) {
899
+ result.push(version)
900
+ }
901
+ return result
902
+ }, [])
903
+ }
904
+ },
889
905
  {
890
906
  regexp: /^electron\s+([\d.]+)\s*-\s*([\d.]+)$/i,
891
907
  select: function (context, from, to) {
@@ -989,7 +1005,7 @@ var QUERIES = [
989
1005
  {
990
1006
  regexp: /^(firefox|ff|fx)\s+esr$/i,
991
1007
  select: function () {
992
- return ['firefox 68']
1008
+ return ['firefox 68', 'firefox 78']
993
1009
  }
994
1010
  },
995
1011
  {
package/node.js CHANGED
@@ -1,3 +1,4 @@
1
+ var feature = require('caniuse-lite/dist/unpacker/feature').default
1
2
  var region = require('caniuse-lite/dist/unpacker/region').default
2
3
  var path = require('path')
3
4
  var fs = require('fs')
@@ -156,12 +157,18 @@ module.exports = {
156
157
  if (!context.dangerousExtend) checkExtend(name)
157
158
  // eslint-disable-next-line security/detect-non-literal-require
158
159
  var queries = require(require.resolve(name, { paths: ['.'] }))
159
- if (!Array.isArray(queries)) {
160
- throw new BrowserslistError(
161
- '`' + name + '` config exports not an array of queries'
162
- )
160
+ if (queries) {
161
+ if (Array.isArray(queries)) {
162
+ return queries
163
+ } else if (typeof queries === 'object') {
164
+ if (!queries.defaults) queries.defaults = []
165
+ return pickEnv(queries, context, name)
166
+ }
163
167
  }
164
- return queries
168
+ throw new BrowserslistError(
169
+ '`' + name + '` config exports not an array of queries' +
170
+ ' or an object of envs'
171
+ )
165
172
  },
166
173
 
167
174
  loadStat: function loadStat (context, name, data) {
@@ -231,6 +238,21 @@ module.exports = {
231
238
  }
232
239
  },
233
240
 
241
+ loadFeature: function loadFeature (features, name) {
242
+ name = name.replace(/[^\w-]/g, '')
243
+ if (features[name]) return
244
+
245
+ // eslint-disable-next-line security/detect-non-literal-require
246
+ var compressed = require('caniuse-lite/data/features/' + name + '.js')
247
+ var stats = feature(compressed).stats
248
+ features[name] = { }
249
+ for (var i in stats) {
250
+ for (var j in stats[i]) {
251
+ features[name][i + ' ' + j] = stats[i][j]
252
+ }
253
+ }
254
+ },
255
+
234
256
  parseConfig: function parseConfig (string) {
235
257
  var result = { defaults: [] }
236
258
  var sections = ['defaults']
@@ -331,6 +353,8 @@ module.exports = {
331
353
  dataTimeChecked = false
332
354
  filenessCache = { }
333
355
  configCache = { }
356
+
357
+ this.cache = { }
334
358
  },
335
359
 
336
360
  oldDataWarning: function oldDataWarning (agentsObj) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "browserslist",
3
- "version": "4.11.1",
3
+ "version": "4.13.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",
@@ -15,17 +15,17 @@
15
15
  "license": "MIT",
16
16
  "repository": "browserslist/browserslist",
17
17
  "dependencies": {
18
- "caniuse-lite": "^1.0.30001038",
19
- "electron-to-chromium": "^1.3.390",
20
- "node-releases": "^1.1.53",
21
- "pkg-up": "^2.0.0"
18
+ "caniuse-lite": "^1.0.30001093",
19
+ "electron-to-chromium": "^1.3.488",
20
+ "escalade": "^3.0.1",
21
+ "node-releases": "^1.1.58"
22
+ },
23
+ "engines": {
24
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
22
25
  },
23
26
  "bin": "./cli.js",
24
27
  "browser": {
25
28
  "./node.js": "./browser.js",
26
29
  "path": false
27
- },
28
- "eslintIgnore": [
29
- "test/fixtures"
30
- ]
30
+ }
31
31
  }
package/update-db.js CHANGED
@@ -1,23 +1,25 @@
1
1
  var childProcess = require('child_process')
2
- var pkgUp = require('pkg-up')
2
+ var escalade = require('escalade/sync')
3
3
  var path = require('path')
4
4
  var fs = require('fs')
5
5
 
6
6
  var BrowserslistError = require('./error')
7
7
 
8
8
  function detectLockfile () {
9
- var packagePath = pkgUp.sync()
10
- if (!packagePath) {
9
+ var packageDir = escalade('.', function (dir, names) {
10
+ return names.indexOf('package.json') !== -1 ? dir : ''
11
+ })
12
+
13
+ if (!packageDir) {
11
14
  throw new BrowserslistError(
12
15
  'Cannot find package.json. ' +
13
16
  'Is it a right project to run npx browserslist --update-db?'
14
17
  )
15
18
  }
16
19
 
17
- var rootDir = path.dirname(packagePath)
18
- var lockfileNpm = path.join(rootDir, 'package-lock.json')
19
- var lockfileYarn = path.join(rootDir, 'yarn.lock')
20
- var lockfilePnpm = path.join(rootDir, 'pnpm-lock.yaml')
20
+ var lockfileNpm = path.join(packageDir, 'package-lock.json')
21
+ var lockfileYarn = path.join(packageDir, 'yarn.lock')
22
+ var lockfilePnpm = path.join(packageDir, 'pnpm-lock.yaml')
21
23
 
22
24
  /* istanbul ignore next */
23
25
  if (fs.existsSync(lockfilePnpm)) {