browserslist 2.3.0 → 2.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.
Files changed (4) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +24 -0
  3. package/index.js +110 -95
  4. package/package.json +15 -7
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
+ ## 2.4
5
+ * Add `last n major versions` query (by John Sanders).
6
+
7
+ ## 2.3.3
8
+ * Fix browsers support.
9
+
10
+ ## 2.3.2
11
+ * Fix `> 0` query for browsers with one version (by Nikolay Solovyov).
12
+
13
+ ## 2.3.1
14
+ * Reduce library size.
15
+
4
16
  ## 2.3
5
17
  * Add `unreleased versions` and `unreleased Chrome versions` queries.
6
18
 
package/README.md CHANGED
@@ -79,6 +79,10 @@ You can specify the versions by queries (case insensitive):
79
79
 
80
80
  * `last 2 versions`: the last 2 versions for each browser.
81
81
  * `last 2 Chrome versions`: the last 2 versions of Chrome browser.
82
+ * `last 2 major versions`: all minor/patch releases of the current
83
+ and previous major versions.
84
+ * `last 2 iOS major versions`: all minor/patch releases of the current
85
+ and previous major versions of iOS Safari.
82
86
  * `> 5%` or `>= 5%`: versions selected by global usage statistics.
83
87
  * `> 5% in US`: uses USA usage statistics. It accepts [two-letter country code].
84
88
  * `> 5% in alt-AS`: uses Asia region usage statistics. List of all region codes
@@ -293,6 +297,26 @@ For example, the query `> 1% in my stats, > 5% in US, 10%` is permitted.
293
297
 
294
298
  [Can I Use]: http://caniuse.com/
295
299
 
300
+ ## Webpack
301
+
302
+ If you plan to use Browserslist on client-side (e. g., tools like CodePen)
303
+ Browserslist could take big part of your bundle — about 150 KB.
304
+
305
+ But the biggest part of this size will be region usage statistics, which could
306
+ be useless for you. You can use `IgnorePlugin` in webpack to cut it:
307
+
308
+ ```js
309
+ const webpackConfig = {
310
+
311
+ plugins: [
312
+ new webpack.IgnorePlugin(/caniuse-lite\/data\/regions/)
313
+ ]
314
+ }
315
+ ```
316
+
317
+ This plugin will reduce Browserslist size from 150 KB to 6 KB. But you loose
318
+ `> 1% in US` queries support.
319
+
296
320
  ## JS API
297
321
 
298
322
  ```js
package/index.js CHANGED
@@ -2,8 +2,8 @@ var path = require('path')
2
2
  var e2c = require('electron-to-chromium/versions')
3
3
  var fs = require('fs')
4
4
 
5
- var caniuse = require('caniuse-lite').agents
6
- var region = require('caniuse-lite').region
5
+ var agents = require('caniuse-lite/dist/unpacker/agents').agents
6
+ var region = require('caniuse-lite/dist/unpacker/region').default
7
7
 
8
8
  function normalize (versions) {
9
9
  return versions.filter(function (version) {
@@ -11,6 +11,29 @@ function normalize (versions) {
11
11
  })
12
12
  }
13
13
 
14
+ function nameMapper (name) {
15
+ return function mapName (version) {
16
+ return name + ' ' + version
17
+ }
18
+ }
19
+
20
+ function getMajor (version) {
21
+ return parseInt(version.split('.')[0])
22
+ }
23
+
24
+ function getMajorVersions (released, number) {
25
+ if (released.length === 0) return []
26
+ var minimum = getMajor(released[released.length - 1]) - parseInt(number) + 1
27
+ var selected = []
28
+ for (var i = released.length - 1; i >= 0; i--) {
29
+ if (minimum > getMajor(released[i])) break
30
+ selected.unshift(released[i])
31
+ }
32
+ return selected
33
+ }
34
+
35
+ var env = process.env
36
+
14
37
  // eslint-disable-next-line security/detect-unsafe-regex
15
38
  var FLOAT_RANGE = /^\d+(\.\d+)?(-\d+(\.\d+)?)*$/
16
39
  var IS_SECTION = /^\s*\[(.+)\]\s*$/
@@ -41,16 +64,11 @@ function fillUsage (result, name, data) {
41
64
  }
42
65
  }
43
66
 
44
- var cacheEnabled = !(
45
- process && process.env && process.env.BROWSERSLIST_DISABLE_CACHE
46
- )
67
+ var cacheEnabled = !env.BROWSERSLIST_DISABLE_CACHE
47
68
  var filenessCache = {}
48
69
  var configCache = {}
49
70
 
50
71
  function isFile (file) {
51
- if (!fs.existsSync) {
52
- return false
53
- }
54
72
  if (file in filenessCache) {
55
73
  return filenessCache[file]
56
74
  }
@@ -73,9 +91,9 @@ function eachParent (file, callback) {
73
91
  function getStat (opts) {
74
92
  if (opts.stats) {
75
93
  return opts.stats
76
- } else if (process.env.BROWSERSLIST_STATS) {
77
- return process.env.BROWSERSLIST_STATS
78
- } else if (opts.path) {
94
+ } else if (env.BROWSERSLIST_STATS) {
95
+ return env.BROWSERSLIST_STATS
96
+ } else if (opts.path && path.resolve) {
79
97
  return eachParent(opts.path, function (dir) {
80
98
  var file = path.join(dir, 'browserslist-stats.json')
81
99
  return isFile(file) ? file : undefined
@@ -96,18 +114,18 @@ function parsePackage (file) {
96
114
  function pickEnv (config, opts) {
97
115
  if (typeof config !== 'object') return config
98
116
 
99
- var env
117
+ var name
100
118
  if (typeof opts.env === 'string') {
101
- env = opts.env
102
- } else if (typeof process.env.BROWSERSLIST_ENV === 'string') {
103
- env = process.env.BROWSERSLIST_ENV
104
- } else if (typeof process.env.NODE_ENV === 'string') {
105
- env = process.env.NODE_ENV
119
+ name = opts.env
120
+ } else if (env.BROWSERSLIST_ENV) {
121
+ name = env.BROWSERSLIST_ENV
122
+ } else if (env.NODE_ENV) {
123
+ name = env.NODE_ENV
106
124
  } else {
107
- env = 'development'
125
+ name = 'development'
108
126
  }
109
127
 
110
- return config[env] || config.defaults
128
+ return config[name] || config.defaults
111
129
  }
112
130
 
113
131
  function generateFilter (sign, version) {
@@ -159,14 +177,14 @@ function browserslist (queries, opts) {
159
177
  if (typeof opts === 'undefined') opts = { }
160
178
 
161
179
  if (!opts.hasOwnProperty('path')) {
162
- opts.path = path.resolve('.')
180
+ opts.path = path.resolve ? path.resolve('.') : '.'
163
181
  }
164
182
 
165
183
  if (typeof queries === 'undefined' || queries === null) {
166
- if (process.env.BROWSERSLIST) {
167
- queries = process.env.BROWSERSLIST
168
- } else if (opts.config || process.env.BROWSERSLIST_CONFIG) {
169
- var file = opts.config || process.env.BROWSERSLIST_CONFIG
184
+ if (env.BROWSERSLIST) {
185
+ queries = env.BROWSERSLIST
186
+ } else if (opts.config || env.BROWSERSLIST_CONFIG) {
187
+ var file = opts.config || env.BROWSERSLIST_CONFIG
170
188
  if (path.basename(file) === 'package.json') {
171
189
  queries = pickEnv(parsePackage(file), opts)
172
190
  } else {
@@ -221,8 +239,8 @@ function browserslist (queries, opts) {
221
239
  selection = selection.slice(4)
222
240
  }
223
241
 
224
- for (var i in browserslist.queries) {
225
- var type = browserslist.queries[i]
242
+ for (var i = 0; i < QUERIES.length; i++) {
243
+ var type = QUERIES[i]
226
244
  var match = selection.match(type.regexp)
227
245
  if (match) {
228
246
  var args = [context].concat(match.slice(1))
@@ -248,7 +266,7 @@ function browserslist (queries, opts) {
248
266
  var name = parts[0]
249
267
  var version = parts[1]
250
268
  if (version === '0') {
251
- return name + ' ' + browserslist.byName(name).versions[0]
269
+ return name + ' ' + byName(name).versions[0]
252
270
  } else {
253
271
  return i
254
272
  }
@@ -329,7 +347,7 @@ browserslist.aliases = {
329
347
  browserslist.versionAliases = { }
330
348
 
331
349
  // Get browser data by alias or case insensitive name
332
- browserslist.byName = function (name) {
350
+ function byName (name) {
333
351
  name = name.toLowerCase()
334
352
  name = browserslist.aliases[name] || name
335
353
  return browserslist.data[name]
@@ -337,8 +355,8 @@ browserslist.byName = function (name) {
337
355
 
338
356
  // Get browser data by alias or case insensitive name and throw error
339
357
  // on unknown browser
340
- browserslist.checkName = function (name) {
341
- var data = browserslist.byName(name)
358
+ function checkName (name) {
359
+ var data = byName(name)
342
360
  if (!data) throw new BrowserslistError('Unknown browser ' + name)
343
361
  return data
344
362
  }
@@ -353,6 +371,8 @@ browserslist.readConfig = function (file) {
353
371
 
354
372
  // Find config, read file and parse it
355
373
  browserslist.findConfig = function (from) {
374
+ if (!path.resolve) return undefined
375
+
356
376
  from = path.resolve(from)
357
377
 
358
378
  var cacheKey = isFile(from) ? path.dirname(from) : from
@@ -370,8 +390,7 @@ browserslist.findConfig = function (from) {
370
390
  try {
371
391
  pkgBrowserslist = parsePackage(pkg)
372
392
  } catch (e) {
373
- console.warn(
374
- '[Browserslist] Could not parse ' + pkg + '. Ignoring it.')
393
+ console.warn('[Browserslist] Could not parse ' + pkg + '. Ignoring it.')
375
394
  }
376
395
  }
377
396
 
@@ -462,69 +481,79 @@ browserslist.clearCaches = function () {
462
481
  configCache = {}
463
482
  }
464
483
 
465
- browserslist.queries = {
484
+ var QUERIES = [
485
+ {
486
+ regexp: /^last\s+(\d+)\s+major versions?$/i,
487
+ select: function (context, versions) {
488
+ var selected = []
489
+ Object.keys(agents).forEach(function (name) {
490
+ var data = byName(name)
491
+ if (!data) return
492
+ var array = getMajorVersions(data.released, versions)
466
493
 
467
- lastVersions: {
494
+ array = array.map(nameMapper(data.name))
495
+ selected = selected.concat(array)
496
+ })
497
+ return selected
498
+ }
499
+ },
500
+ {
468
501
  regexp: /^last\s+(\d+)\s+versions?$/i,
469
502
  select: function (context, versions) {
470
503
  var selected = []
471
- Object.keys(caniuse).forEach(function (name) {
472
- var data = browserslist.byName(name)
504
+ Object.keys(agents).forEach(function (name) {
505
+ var data = byName(name)
473
506
  if (!data) return
474
507
  var array = data.released.slice(-versions)
475
508
 
476
- array = array.map(function (v) {
477
- return data.name + ' ' + v
478
- })
509
+ array = array.map(nameMapper(data.name))
479
510
  selected = selected.concat(array)
480
511
  })
481
512
  return selected
482
513
  }
483
514
  },
484
-
485
- lastByBrowser: {
515
+ {
516
+ regexp: /^last\s+(\d+)\s+(\w+)\s+major versions?$/i,
517
+ select: function (context, versions, name) {
518
+ var data = checkName(name)
519
+ var validVersions = getMajorVersions(data.released, versions)
520
+ return validVersions.map(nameMapper(data.name))
521
+ }
522
+ },
523
+ {
486
524
  regexp: /^last\s+(\d+)\s+(\w+)\s+versions?$/i,
487
525
  select: function (context, versions, name) {
488
- var data = browserslist.checkName(name)
489
- return data.released.slice(-versions).map(function (v) {
490
- return data.name + ' ' + v
491
- })
526
+ var data = checkName(name)
527
+ return data.released.slice(-versions).map(nameMapper(data.name))
492
528
  }
493
529
  },
494
-
495
- unreleased: {
530
+ {
496
531
  regexp: /^unreleased\s+versions$/i,
497
532
  select: function () {
498
533
  var selected = []
499
- Object.keys(caniuse).forEach(function (name) {
500
- var data = browserslist.byName(name)
534
+ Object.keys(agents).forEach(function (name) {
535
+ var data = byName(name)
501
536
  if (!data) return
502
537
  var array = data.versions.filter(function (v) {
503
538
  return data.released.indexOf(v) === -1
504
539
  })
505
540
 
506
- array = array.map(function (v) {
507
- return data.name + ' ' + v
508
- })
541
+ array = array.map(nameMapper(data.name))
509
542
  selected = selected.concat(array)
510
543
  })
511
544
  return selected
512
545
  }
513
546
  },
514
-
515
- unreleasedByBrowser: {
547
+ {
516
548
  regexp: /^unreleased\s+(\w+)\s+versions?$/i,
517
549
  select: function (context, name) {
518
- var data = browserslist.checkName(name)
550
+ var data = checkName(name)
519
551
  return data.versions.filter(function (v) {
520
552
  return data.released.indexOf(v) === -1
521
- }).map(function (v) {
522
- return data.name + ' ' + v
523
- })
553
+ }).map(nameMapper(data.name))
524
554
  }
525
555
  },
526
-
527
- globalStatistics: {
556
+ {
528
557
  regexp: /^(>=?)\s*(\d*\.?\d+)%$/,
529
558
  select: function (context, sign, popularity) {
530
559
  popularity = parseFloat(popularity)
@@ -543,8 +572,7 @@ browserslist.queries = {
543
572
  return result
544
573
  }
545
574
  },
546
-
547
- customStatistics: {
575
+ {
548
576
  regexp: /^(>=?)\s*(\d*\.?\d+)%\s+in\s+my\s+stats$/,
549
577
  select: function (context, sign, popularity) {
550
578
  popularity = parseFloat(popularity)
@@ -567,8 +595,7 @@ browserslist.queries = {
567
595
  return result
568
596
  }
569
597
  },
570
-
571
- countryStatistics: {
598
+ {
572
599
  regexp: /^(>=?)\s*(\d*\.?\d+)%\s+in\s+((alt-)?\w\w)$/,
573
600
  select: function (context, sign, popularity, place) {
574
601
  popularity = parseFloat(popularity)
@@ -596,8 +623,7 @@ browserslist.queries = {
596
623
  return result
597
624
  }
598
625
  },
599
-
600
- electronRange: {
626
+ {
601
627
  regexp: /^electron\s+([\d.]+)\s*-\s*([\d.]+)$/i,
602
628
  select: function (context, from, to) {
603
629
  if (!e2c[from]) {
@@ -618,11 +644,10 @@ browserslist.queries = {
618
644
  })
619
645
  }
620
646
  },
621
-
622
- range: {
647
+ {
623
648
  regexp: /^(\w+)\s+([\d.]+)\s*-\s*([\d.]+)$/i,
624
649
  select: function (context, name, from, to) {
625
- var data = browserslist.checkName(name)
650
+ var data = checkName(name)
626
651
  from = parseFloat(normalizeVersion(data, from) || from)
627
652
  to = parseFloat(normalizeVersion(data, to) || to)
628
653
 
@@ -631,13 +656,10 @@ browserslist.queries = {
631
656
  return parsed >= from && parsed <= to
632
657
  }
633
658
 
634
- return data.released.filter(filter).map(function (v) {
635
- return data.name + ' ' + v
636
- })
659
+ return data.released.filter(filter).map(nameMapper(data.name))
637
660
  }
638
661
  },
639
-
640
- electronVersions: {
662
+ {
641
663
  regexp: /^electron\s*(>=?|<=?)\s*([\d.]+)$/i,
642
664
  select: function (context, sign, version) {
643
665
  return Object.keys(e2c)
@@ -647,12 +669,11 @@ browserslist.queries = {
647
669
  })
648
670
  }
649
671
  },
650
-
651
- versions: {
672
+ {
652
673
  regexp: /^(\w+)\s*(>=?|<=?)\s*([\d.]+)$/,
653
674
  select: function (context, name, sign, version) {
654
- var data = browserslist.checkName(name)
655
- var alias = normalizeVersion(data, version)
675
+ var data = checkName(name)
676
+ var alias = browserslist.versionAliases[data.name][version]
656
677
  if (alias) {
657
678
  version = alias
658
679
  }
@@ -663,22 +684,19 @@ browserslist.queries = {
663
684
  })
664
685
  }
665
686
  },
666
-
667
- esr: {
687
+ {
668
688
  regexp: /^(firefox|ff|fx)\s+esr$/i,
669
689
  select: function () {
670
690
  return ['firefox 52']
671
691
  }
672
692
  },
673
-
674
- opMini: {
693
+ {
675
694
  regexp: /(operamini|op_mini)\s+all/i,
676
695
  select: function () {
677
696
  return ['op_mini all']
678
697
  }
679
698
  },
680
-
681
- electron: {
699
+ {
682
700
  regexp: /^electron\s+([\d.]+)$/i,
683
701
  select: function (context, version) {
684
702
  var chrome = e2c[version]
@@ -689,12 +707,11 @@ browserslist.queries = {
689
707
  return ['chrome ' + chrome]
690
708
  }
691
709
  },
692
-
693
- direct: {
710
+ {
694
711
  regexp: /^(\w+)\s+(tp|[\d.]+)$/i,
695
712
  select: function (context, name, version) {
696
713
  if (/^tp$/i.test(version)) version = 'TP'
697
- var data = browserslist.checkName(name)
714
+ var data = checkName(name)
698
715
  var alias = normalizeVersion(data, version)
699
716
  if (alias) {
700
717
  version = alias
@@ -715,25 +732,23 @@ browserslist.queries = {
715
732
  return [data.name + ' ' + version]
716
733
  }
717
734
  },
718
-
719
- defaults: {
735
+ {
720
736
  regexp: /^defaults$/i,
721
737
  select: function () {
722
738
  return browserslist(browserslist.defaults)
723
739
  }
724
740
  }
725
-
726
- };
741
+ ];
727
742
 
728
743
  // Get and convert Can I Use data
729
744
 
730
745
  (function () {
731
- for (var name in caniuse) {
732
- var browser = caniuse[name]
746
+ for (var name in agents) {
747
+ var browser = agents[name]
733
748
  browserslist.data[name] = {
734
749
  name: name,
735
- versions: normalize(caniuse[name].versions),
736
- released: normalize(caniuse[name].versions.slice(0, -3))
750
+ versions: normalize(agents[name].versions),
751
+ released: normalize(agents[name].versions.slice(0, -3))
737
752
  }
738
753
  fillUsage(browserslist.usage.global, name, browser.usage_global)
739
754
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "browserslist",
3
- "version": "2.3.0",
3
+ "version": "2.4.0",
4
4
  "description": "Share browsers list between different front-end tools, like Autoprefixer, Stylelint and babel-env-preset",
5
5
  "keywords": [
6
6
  "caniuse",
@@ -10,13 +10,13 @@
10
10
  "license": "MIT",
11
11
  "repository": "ai/browserslist",
12
12
  "dependencies": {
13
- "caniuse-lite": "^1.0.30000710",
14
- "electron-to-chromium": "^1.3.17"
13
+ "caniuse-lite": "^1.0.30000718",
14
+ "electron-to-chromium": "^1.3.18"
15
15
  },
16
16
  "bin": "./cli.js",
17
17
  "devDependencies": {
18
18
  "cross-spawn": "^5.1.0",
19
- "eslint": "^4.3.0",
19
+ "eslint": "^4.5.0",
20
20
  "eslint-config-logux": "^16.0.0",
21
21
  "eslint-config-standard": "^10.2.1",
22
22
  "eslint-plugin-es5": "^1.1.0",
@@ -27,8 +27,9 @@
27
27
  "eslint-plugin-security": "^1.4.0",
28
28
  "eslint-plugin-standard": "^3.0.1",
29
29
  "jest": "^20.0.4",
30
- "lint-staged": "^4.0.2",
30
+ "lint-staged": "^4.0.4",
31
31
  "pre-commit": "^1.1.3",
32
+ "size-limit": "^0.10.0",
32
33
  "yaspeller-ci": "^0.6.0"
33
34
  },
34
35
  "eslintConfig": {
@@ -52,17 +53,24 @@
52
53
  }
53
54
  }
54
55
  },
56
+ "size-limit": [
57
+ {
58
+ "path": "index.js",
59
+ "limit": "152 KB"
60
+ }
61
+ ],
55
62
  "scripts": {
56
63
  "lint-staged": "lint-staged",
57
64
  "spellcheck": "yaspeller-ci README.md CHANGELOG.md",
58
- "lint": "eslint *.js test/*.js",
59
- "test": "jest --coverage && yarn lint && yarn spellcheck"
65
+ "lint": "eslint *.js test/*.js __mocks__/*.js",
66
+ "test": "jest --coverage && yarn lint && yarn spellcheck && size-limit"
60
67
  },
61
68
  "lint-staged": {
62
69
  "*.md": "yaspeller-ci",
63
70
  "*.js": "eslint"
64
71
  },
65
72
  "browser": {
73
+ "path": false,
66
74
  "fs": false
67
75
  },
68
76
  "pre-commit": [