browserslist 4.5.5 → 4.6.2

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.
Files changed (4) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +46 -36
  3. package/index.js +88 -44
  4. package/package.json +4 -4
package/CHANGELOG.md CHANGED
@@ -1,6 +1,18 @@
1
1
  # Change Log
2
2
  This project adheres to [Semantic Versioning](http://semver.org/).
3
3
 
4
+ ## 4.6.2
5
+ * Fix `last x version` and similar queries for Android (by Tony Ross).
6
+
7
+ ## 4.6.1
8
+ * Fix patch version support for Electron (by Kilian Valkhof).
9
+
10
+ ## 4.6
11
+ * Add `mobileToDesktop` option (by Nicolò Ribaudo).
12
+
13
+ ## 4.5.6
14
+ * Make `Node > 5` and `node > 5` queries case insensitive.
15
+
4
16
  ## 4.5.5
5
17
  * Fix CLI help (by Marcel Gerber).
6
18
  * Add KaiOS browser to docs.
package/README.md CHANGED
@@ -18,15 +18,13 @@ front-end tools. It is used in:
18
18
  All tools will find target browsers automatically,
19
19
  when you add the following to `package.json`:
20
20
 
21
- ```json
22
- {
21
+ ```js
23
22
  "browserslist": [
24
23
  "last 1 version",
25
24
  "> 1%",
26
25
  "maintained node versions",
27
26
  "not dead"
28
27
  ]
29
- }
30
28
  ```
31
29
 
32
30
  Or in `.browserslistrc` config:
@@ -92,6 +90,34 @@ You can test Browserslist queries in [online demo].
92
90
  [`browserslist-browserstack`]: https://github.com/xeroxinteractive/browserslist-browserstack
93
91
 
94
92
 
93
+ ## Best Practices
94
+
95
+ * Select browsers directly (`last 2 Chrome versions`) only if you are making
96
+ a web app for a kiosk with one browser. There are a lot of browsers
97
+ on the market. If you are making general web app you should respect
98
+ browsers diversity.
99
+ * There is a `defaults` query, which gives a reasonable configuration
100
+ for most users:
101
+
102
+ ```json
103
+ "browserslist": [
104
+ "defaults"
105
+ ]
106
+ ```
107
+
108
+ * If you want to change the default set of browsers we recommend to combine
109
+ `last 1 version`, `not dead` with `> 0.2%` (or `> 1% in US`,
110
+ `> 1% in my stats`). `last n versions` adds too many dead browsers
111
+ and does not add popular old versions. Choosing a percentage above `0.2%`
112
+ will in the long run make popular browsers even more popular. We might run
113
+ into a monopoly and stagnation situation, as we had with Internet Explorer 6.
114
+ Please use this setting with caution.
115
+ * Don’t remove browsers just because you don’t know them. Opera Mini has
116
+ 100 million users in Africa and it is more popular in the global market
117
+ than Microsoft Edge. Chinese QQ Browsers has more market share than Firefox
118
+ and desktop Safari altogether.
119
+
120
+
95
121
  ## Queries
96
122
 
97
123
  Browserslist will use browsers and Node.js versions query
@@ -99,11 +125,10 @@ from one of this sources:
99
125
 
100
126
  1. `browserslist` key in `package.json` file in current or parent directories.
101
127
  **We recommend this way.**
102
- 2. Tool options. For example `browsers` option in Autoprefixer.
103
- 3. `BROWSERSLIST` environment variable.
104
- 4. `browserslist` config file in current or parent directories.
105
- 5. `.browserslistrc` config file in current or parent directories.
106
- 6. If the above methods did not produce a valid result
128
+ 2. `.browserslistrc` config file in current or parent directories.
129
+ 3. `browserslist` config file in current or parent directories.
130
+ 4. `BROWSERSLIST` environment variable.
131
+ 5. If the above methods did not produce a valid result
107
132
  Browserslist will use defaults:
108
133
  `> 0.5%, last 2 versions, Firefox ESR, not dead`.
109
134
 
@@ -132,25 +157,6 @@ _A quick way to test your query is to do `npx browserslist '> 0.5%, not IE 11'`
132
157
  in your terminal._
133
158
 
134
159
 
135
- ### Best Practices
136
-
137
- * Select browsers directly (`last 2 Chrome versions`) only if you are making
138
- a web app for a kiosk with one browser. There are a lot of browsers
139
- on the market. If you are making general web app you should respect
140
- browsers diversity.
141
- * If you want to change the default set of browsers we recommend to combine
142
- `last 1 version`, `not dead` with `> 0.2%` (or `> 1% in US`,
143
- `> 1% in my stats`). `last n versions` adds too many dead browsers
144
- and does not add popular old versions. Choosing a percentage above `0.2%`
145
- will in the long run make popular browsers even more popular. We might run
146
- into a monopoly and stagnation situation, as we had with Internet Explorer 6.
147
- Please use this setting with caution.
148
- * Don’t remove browsers just because you don’t know them. Opera Mini has
149
- 100 million users in Africa and it is more popular in the global market
150
- than Microsoft Edge. Chinese QQ Browsers has more market share than Firefox
151
- and desktop Safari altogether.
152
-
153
-
154
160
  ### Full List
155
161
 
156
162
  You can specify the browser and Node.js versions by queries (case insensitive):
@@ -460,16 +466,16 @@ For example, the query `> 1% in my stats, > 5% in US, 10%` is permitted.
460
466
  ## JS API
461
467
 
462
468
  ```js
463
- var browserslist = require('browserslist');
469
+ const browserslist = require('browserslist')
464
470
 
465
471
  // Your CSS/JS build tool code
466
- var process = function (source, opts) {
467
- var browsers = browserslist(opts.browsers, {
468
- stats: opts.stats,
469
- path: opts.file,
470
- env: opts.env
471
- });
472
- // Your code to add features for selected browsers
472
+ function process (source, opts) {
473
+ const browsers = browserslist(opts.overrideBrowserslist, {
474
+ stats: opts.stats,
475
+ path: opts.file,
476
+ env: opts.env
477
+ })
478
+ // Your code to add features for selected browsers
473
479
  }
474
480
  ```
475
481
 
@@ -490,6 +496,10 @@ Options:
490
496
  Default is `false.`
491
497
  * `dangerousExtend`: Disable security checks for `extend` query.
492
498
  Default is `false.`
499
+ * `mobileToDesktop`: Use desktop browsers if Can I Use doesn’t have data
500
+ about this mobile version. For instance, Browserslist will return
501
+ `chrome 20` on `and_chr 20` query (Can I Use has only data only about
502
+ latest versions of mobile browsers). Default is `false`.
493
503
 
494
504
  For non-JS environment and debug purpose you can use CLI tool:
495
505
 
@@ -554,7 +564,7 @@ for the duration of the hosting process.
554
564
  To clear these caches, use:
555
565
 
556
566
  ```js
557
- browserslist.clearCaches();
567
+ browserslist.clearCaches()
558
568
  ```
559
569
 
560
570
  To disable the caching altogether, set the `BROWSERSLIST_DISABLE_CACHE`
package/index.js CHANGED
@@ -33,6 +33,17 @@ function normalize (versions) {
33
33
  })
34
34
  }
35
35
 
36
+ function normalizeElectron (version) {
37
+ var versionToUse = version
38
+ if (version.split('.').length === 3) {
39
+ versionToUse = version
40
+ .split('.')
41
+ .slice(0, -1)
42
+ .join('.')
43
+ }
44
+ return versionToUse
45
+ }
46
+
36
47
  function nameMapper (name) {
37
48
  return function mapName (version) {
38
49
  return name + ' ' + version
@@ -136,11 +147,28 @@ function compareSemver (a, b) {
136
147
  )
137
148
  }
138
149
 
139
- function normalizeVersion (data, version) {
150
+ function resolveVersion (data, version) {
140
151
  if (data.versions.indexOf(version) !== -1) {
141
152
  return version
142
153
  } else if (browserslist.versionAliases[data.name][version]) {
143
154
  return browserslist.versionAliases[data.name][version]
155
+ } else {
156
+ return false
157
+ }
158
+ }
159
+
160
+ function normalizeVersion (data, version, context) {
161
+ var resolved = resolveVersion(data, version)
162
+ if (
163
+ !resolved &&
164
+ context.mobileToDesktop &&
165
+ browserslist.desktopNames[data.name]
166
+ ) {
167
+ var alias = checkName(browserslist.desktopNames[data.name])
168
+ resolved = resolveVersion(alias, version)
169
+ }
170
+ if (resolved) {
171
+ return resolved
144
172
  } else if (data.versions.length === 1) {
145
173
  return data.versions[0]
146
174
  } else {
@@ -179,6 +207,18 @@ function unknownQuery (query) {
179
207
  )
180
208
  }
181
209
 
210
+ function filterAndroid (list, versions) {
211
+ var released = browserslist.data.android.released
212
+ var firstEvergreen = 37
213
+ var last = released[released.length - 1]
214
+ var diff = last - firstEvergreen - versions // First Android Evergreen
215
+ if (diff > 0) {
216
+ return list.slice(-1)
217
+ } else {
218
+ return list.slice(diff - 1)
219
+ }
220
+ }
221
+
182
222
  /**
183
223
  * Resolves queries into a browser list.
184
224
  * @param {string|string[]} queries Queries to combine.
@@ -274,6 +314,9 @@ function resolve (queries, context) {
274
314
  * version in direct query.
275
315
  * @param {boolean} [opts.dangerousExtend] Disable security checks
276
316
  * for extend query.
317
+ * @param {boolean} [opts.mobileToDesktop] Alias mobile browsers to the desktop
318
+ * version when Can I Use doesn't have
319
+ * data about the specified version.
277
320
  * @returns {string[]} Array with browser names in Can I Use.
278
321
  *
279
322
  * @example
@@ -302,7 +345,8 @@ function browserslist (queries, opts) {
302
345
 
303
346
  var context = {
304
347
  ignoreUnknownVersions: opts.ignoreUnknownVersions,
305
- dangerousExtend: opts.dangerousExtend
348
+ dangerousExtend: opts.dangerousExtend,
349
+ mobileToDesktop: opts.mobileToDesktop
306
350
  }
307
351
 
308
352
  env.oldDataWarning(browserslist.data)
@@ -427,6 +471,15 @@ browserslist.aliases = {
427
471
  qqandroid: 'and_qq'
428
472
  }
429
473
 
474
+ // Can I Use only provides a few versions for some browsers (e.g. and_chr).
475
+ // Fallback to a similar browser for unknown versions
476
+ browserslist.desktopNames = {
477
+ and_chr: 'chrome',
478
+ and_ff: 'firefox',
479
+ ie_mob: 'ie',
480
+ op_mob: 'opera'
481
+ }
482
+
430
483
  // Aliases to work with joined versions like `ios_saf 7.0-7.1`
431
484
  browserslist.versionAliases = { }
432
485
 
@@ -496,15 +549,15 @@ browserslist.coverage = function (browsers, stats) {
496
549
 
497
550
  var QUERIES = [
498
551
  {
499
- regexp: /^last\s+(\d+)\s+major versions?$/i,
552
+ regexp: /^last\s+(\d+)\s+major\s+versions?$/i,
500
553
  select: function (context, versions) {
501
554
  return Object.keys(agents).reduce(function (selected, name) {
502
555
  var data = byName(name)
503
556
  if (!data) return selected
504
- var array = getMajorVersions(data.released, versions)
505
-
506
- array = array.map(nameMapper(data.name))
507
- return selected.concat(array)
557
+ var list = getMajorVersions(data.released, versions)
558
+ list = list.map(nameMapper(data.name))
559
+ if (data.name === 'android') list = filterAndroid(list, versions)
560
+ return selected.concat(list)
508
561
  }, [])
509
562
  }
510
563
  },
@@ -514,15 +567,15 @@ var QUERIES = [
514
567
  return Object.keys(agents).reduce(function (selected, name) {
515
568
  var data = byName(name)
516
569
  if (!data) return selected
517
- var array = data.released.slice(-versions)
518
-
519
- array = array.map(nameMapper(data.name))
520
- return selected.concat(array)
570
+ var list = data.released.slice(-versions)
571
+ list = list.map(nameMapper(data.name))
572
+ if (data.name === 'android') list = filterAndroid(list, versions)
573
+ return selected.concat(list)
521
574
  }, [])
522
575
  }
523
576
  },
524
577
  {
525
- regexp: /^last\s+(\d+)\s+electron\s+major versions?$/i,
578
+ regexp: /^last\s+(\d+)\s+electron\s+major\s+versions?$/i,
526
579
  select: function (context, versions) {
527
580
  var validVersions = getMajorVersions(Object.keys(e2c).reverse(), versions)
528
581
  return validVersions.map(function (i) {
@@ -531,11 +584,13 @@ var QUERIES = [
531
584
  }
532
585
  },
533
586
  {
534
- regexp: /^last\s+(\d+)\s+(\w+)\s+major versions?$/i,
587
+ regexp: /^last\s+(\d+)\s+(\w+)\s+major\s+versions?$/i,
535
588
  select: function (context, versions, name) {
536
589
  var data = checkName(name)
537
590
  var validVersions = getMajorVersions(data.released, versions)
538
- return validVersions.map(nameMapper(data.name))
591
+ var list = validVersions.map(nameMapper(data.name))
592
+ if (data.name === 'android') list = filterAndroid(list, versions)
593
+ return list
539
594
  }
540
595
  },
541
596
  {
@@ -550,7 +605,9 @@ var QUERIES = [
550
605
  regexp: /^last\s+(\d+)\s+(\w+)\s+versions?$/i,
551
606
  select: function (context, versions, name) {
552
607
  var data = checkName(name)
553
- return data.released.slice(-versions).map(nameMapper(data.name))
608
+ var list = data.released.slice(-versions).map(nameMapper(data.name))
609
+ if (data.name === 'android') list = filterAndroid(list, versions)
610
+ return list
554
611
  }
555
612
  },
556
613
  {
@@ -559,12 +616,11 @@ var QUERIES = [
559
616
  return Object.keys(agents).reduce(function (selected, name) {
560
617
  var data = byName(name)
561
618
  if (!data) return selected
562
- var array = data.versions.filter(function (v) {
619
+ var list = data.versions.filter(function (v) {
563
620
  return data.released.indexOf(v) === -1
564
621
  })
565
-
566
- array = array.map(nameMapper(data.name))
567
- return selected.concat(array)
622
+ list = list.map(nameMapper(data.name))
623
+ return selected.concat(list)
568
624
  }, [])
569
625
  }
570
626
  },
@@ -603,7 +659,6 @@ var QUERIES = [
603
659
  select: function (context, sign, popularity) {
604
660
  popularity = parseFloat(popularity)
605
661
  var usage = browserslist.usage.global
606
-
607
662
  return Object.keys(usage).reduce(function (result, version) {
608
663
  if (sign === '>') {
609
664
  if (usage[version] > popularity) {
@@ -628,13 +683,10 @@ var QUERIES = [
628
683
  regexp: /^(>=?|<=?)\s*(\d*\.?\d+)%\s+in\s+my\s+stats$/,
629
684
  select: function (context, sign, popularity) {
630
685
  popularity = parseFloat(popularity)
631
-
632
686
  if (!context.customUsage) {
633
687
  throw new BrowserslistError('Custom usage statistics was not provided')
634
688
  }
635
-
636
689
  var usage = context.customUsage
637
-
638
690
  return Object.keys(usage).reduce(function (result, version) {
639
691
  if (sign === '>') {
640
692
  if (usage[version] > popularity) {
@@ -659,16 +711,13 @@ var QUERIES = [
659
711
  regexp: /^(>=?|<=?)\s*(\d*\.?\d+)%\s+in\s+((alt-)?\w\w)$/,
660
712
  select: function (context, sign, popularity, place) {
661
713
  popularity = parseFloat(popularity)
662
-
663
714
  if (place.length === 2) {
664
715
  place = place.toUpperCase()
665
716
  } else {
666
717
  place = place.toLowerCase()
667
718
  }
668
-
669
719
  env.loadCountry(browserslist.usage, place)
670
720
  var usage = browserslist.usage[place]
671
-
672
721
  return Object.keys(usage).reduce(function (result, version) {
673
722
  if (sign === '>') {
674
723
  if (usage[version] > popularity) {
@@ -693,7 +742,6 @@ var QUERIES = [
693
742
  regexp: /^cover\s+(\d*\.?\d+)%(\s+in\s+(my\s+stats|(alt-)?\w\w))?$/,
694
743
  select: function (context, coverage, statMode) {
695
744
  coverage = parseFloat(coverage)
696
-
697
745
  var usage = browserslist.usage.global
698
746
  if (statMode) {
699
747
  if (statMode.match(/^\s+in\s+my\s+stats$/)) {
@@ -715,39 +763,35 @@ var QUERIES = [
715
763
  usage = browserslist.usage[place]
716
764
  }
717
765
  }
718
-
719
766
  var versions = Object.keys(usage).sort(function (a, b) {
720
767
  return usage[b] - usage[a]
721
768
  })
722
-
723
769
  var coveraged = 0
724
770
  var result = []
725
771
  var version
726
772
  for (var i = 0; i <= versions.length; i++) {
727
773
  version = versions[i]
728
774
  if (usage[version] === 0) break
729
-
730
775
  coveraged += usage[version]
731
776
  result.push(version)
732
777
  if (coveraged >= coverage) break
733
778
  }
734
-
735
779
  return result
736
780
  }
737
781
  },
738
782
  {
739
783
  regexp: /^electron\s+([\d.]+)\s*-\s*([\d.]+)$/i,
740
784
  select: function (context, from, to) {
741
- if (!e2c[from]) {
785
+ var fromToUse = normalizeElectron(from)
786
+ var toToUse = normalizeElectron(to)
787
+ if (!e2c[fromToUse]) {
742
788
  throw new BrowserslistError('Unknown version ' + from + ' of electron')
743
789
  }
744
- if (!e2c[to]) {
790
+ if (!e2c[toToUse]) {
745
791
  throw new BrowserslistError('Unknown version ' + to + ' of electron')
746
792
  }
747
-
748
793
  from = parseFloat(from)
749
794
  to = parseFloat(to)
750
-
751
795
  return Object.keys(e2c).filter(function (i) {
752
796
  var parsed = parseFloat(i)
753
797
  return parsed >= from && parsed <= to
@@ -760,29 +804,28 @@ var QUERIES = [
760
804
  regexp: /^(\w+)\s+([\d.]+)\s*-\s*([\d.]+)$/i,
761
805
  select: function (context, name, from, to) {
762
806
  var data = checkName(name)
763
- from = parseFloat(normalizeVersion(data, from) || from)
764
- to = parseFloat(normalizeVersion(data, to) || to)
765
-
807
+ from = parseFloat(normalizeVersion(data, from, context) || from)
808
+ to = parseFloat(normalizeVersion(data, to, context) || to)
766
809
  function filter (v) {
767
810
  var parsed = parseFloat(v)
768
811
  return parsed >= from && parsed <= to
769
812
  }
770
-
771
813
  return data.released.filter(filter).map(nameMapper(data.name))
772
814
  }
773
815
  },
774
816
  {
775
817
  regexp: /^electron\s*(>=?|<=?)\s*([\d.]+)$/i,
776
818
  select: function (context, sign, version) {
819
+ var versionToUse = normalizeElectron(version)
777
820
  return Object.keys(e2c)
778
- .filter(generateFilter(sign, version))
821
+ .filter(generateFilter(sign, versionToUse))
779
822
  .map(function (i) {
780
823
  return 'chrome ' + e2c[i]
781
824
  })
782
825
  }
783
826
  },
784
827
  {
785
- regexp: /^node\s*(>=?|<=?)\s*([\d.]+)$/,
828
+ regexp: /^node\s*(>=?|<=?)\s*([\d.]+)$/i,
786
829
  select: function (context, sign, version) {
787
830
  var nodeVersions = jsReleases.filter(function (i) {
788
831
  return i.name === 'nodejs'
@@ -826,7 +869,8 @@ var QUERIES = [
826
869
  {
827
870
  regexp: /^electron\s+([\d.]+)$/i,
828
871
  select: function (context, version) {
829
- var chrome = e2c[version]
872
+ var versionToUse = normalizeElectron(version)
873
+ var chrome = e2c[versionToUse]
830
874
  if (!chrome) {
831
875
  throw new BrowserslistError(
832
876
  'Unknown version ' + version + ' of electron')
@@ -879,7 +923,7 @@ var QUERIES = [
879
923
  select: function (context, name, version) {
880
924
  if (/^tp$/i.test(version)) version = 'TP'
881
925
  var data = checkName(name)
882
- var alias = normalizeVersion(data, version)
926
+ var alias = normalizeVersion(data, version, context)
883
927
  if (alias) {
884
928
  version = alias
885
929
  } else {
@@ -888,7 +932,7 @@ var QUERIES = [
888
932
  } else {
889
933
  alias = version.replace(/\.0$/, '')
890
934
  }
891
- alias = normalizeVersion(data, alias)
935
+ alias = normalizeVersion(data, alias, context)
892
936
  if (alias) {
893
937
  version = alias
894
938
  } else if (context.ignoreUnknownVersions) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "browserslist",
3
- "version": "4.5.5",
3
+ "version": "4.6.2",
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,9 +11,9 @@
11
11
  "license": "MIT",
12
12
  "repository": "browserslist/browserslist",
13
13
  "dependencies": {
14
- "caniuse-lite": "^1.0.30000960",
15
- "electron-to-chromium": "^1.3.124",
16
- "node-releases": "^1.1.14"
14
+ "caniuse-lite": "^1.0.30000974",
15
+ "electron-to-chromium": "^1.3.150",
16
+ "node-releases": "^1.1.23"
17
17
  },
18
18
  "bin": "./cli.js",
19
19
  "browser": {