From 3c51c3be85bb0d1bdb87ea0d6632f1c256912f27 Mon Sep 17 00:00:00 2001 From: Dimitri Staessens Date: Sun, 6 Oct 2019 21:37:45 +0200 Subject: build: Add some required modules for node --- node_modules/browserslist/CHANGELOG.md | 402 +++++++++++++ node_modules/browserslist/LICENSE | 20 + node_modules/browserslist/README.md | 589 +++++++++++++++++++ node_modules/browserslist/browser.js | 41 ++ node_modules/browserslist/cli.js | 135 +++++ node_modules/browserslist/error.js | 12 + node_modules/browserslist/index.js | 996 +++++++++++++++++++++++++++++++++ node_modules/browserslist/node.js | 318 +++++++++++ node_modules/browserslist/package.json | 66 +++ 9 files changed, 2579 insertions(+) create mode 100644 node_modules/browserslist/CHANGELOG.md create mode 100644 node_modules/browserslist/LICENSE create mode 100644 node_modules/browserslist/README.md create mode 100644 node_modules/browserslist/browser.js create mode 100755 node_modules/browserslist/cli.js create mode 100644 node_modules/browserslist/error.js create mode 100644 node_modules/browserslist/index.js create mode 100644 node_modules/browserslist/node.js create mode 100644 node_modules/browserslist/package.json (limited to 'node_modules/browserslist') diff --git a/node_modules/browserslist/CHANGELOG.md b/node_modules/browserslist/CHANGELOG.md new file mode 100644 index 0000000..79fc322 --- /dev/null +++ b/node_modules/browserslist/CHANGELOG.md @@ -0,0 +1,402 @@ +# Change Log +This project adheres to [Semantic Versioning](http://semver.org/). + +## 4.7 +* Add PhantomJS queries. +* Improve docs (by Dorian Koehring). + +## 4.6.6 +* Remove Safari from `dead` query. + +## 4.6.5 +* Add Samsung 4 browser to `dead` query. +* Remove dirty fix for `android all` error. + +## 4.6.4 +* Add Firefox 68 to `Firefox ESR` query. + +## 4.6.3 +* Dirty fix for `android all` error. + +## 4.6.2 +* Fix `last x version` and similar queries for Android (by Tony Ross). + +## 4.6.1 +* Fix patch version support for Electron (by Kilian Valkhof). + +## 4.6 +* Add `mobileToDesktop` option (by Nicolò Ribaudo). + +## 4.5.6 +* Make `Node > 5` and `node > 5` queries case insensitive. + +## 4.5.5 +* Fix CLI help (by Marcel Gerber). +* Add KaiOS browser to docs. + +## 4.5.4 +* Update docs (by Andrew Leedham and Dan Onoshko). + +## 4.5.3 +* Fix splitting string to queries. + +## 4.5.2 +* Show default browsers in CLI on project without config. + +## 4.5.1 +* Improve text for the warning about outdated `caniuse-lite`. + +## 4.5 +* Add `>=`, `>`, and `<=` support for Node.js version (by Mathspy Terabithian). + +## 4.4.2 +* Allow to have string in `package.json` (by @dmarkhas). + +## 4.4.1 +* Allow to use `.` in scope name of shareable config (by Gustav Nikolaj). + +## 4.4 +* Added `and` and `or` keywords to combine queries (by Jon Ege Ronnenberg). + +## 4.3.7 +* Fix fraction years support in `last 1.5 years` (by Clément P). +* Fix version-less browser support. + +## 4.3.6 +* Fix version-less browser support in custom statistics (by Alex Walter). + +## 4.3.5 +* Fix `not` query for wrong Can I Use data. + +## 4.3.4 +* Allow to update `node-releases` without new Browserslist releases. + +## 4.3.3 +* Fix Node.js 11 support. + +## 4.3.2 +* Fix `Unknown version 11 of Node.js` error (by Dan Onoshko). + +## 4.3.1 +* Fix conflict between `caniuse-lite` and custom browsers statistics. + +## 4.3 +* Allow to use `extends browserslist-config-a/file` (by @Schweinepriester). + +## 4.2.1 +* Use new `node-releases` support (by Sergey Rubanov). + +## 4.2 +* Add `--json` argument for CLI. +* Allow to pass multiple areas in CLI by `--coverage=US,alt-AS,global`. + +## 4.1.2 +* Better `unknow query` error message. +* Use latest `node-releases`. + +## 4.1.1 +* Update Firefox ESR versions. + +## 4.1 +* Add `current node` query. +* Add contributors widget to docs (by Sergey Surkov). + +## 4.0.2 +* Fix new `node-releases` support (by Sergey Rubanov). +* Fix error text (by Josh Smith). + +## 4.0.1 +* Reduce npm package size. +* Fix docs. + +## 4.0.0 “Erinaceus amurensis” +* Add `node X` and `maintained node versions` queries (by Pavel Vostrikov). +* Remove Node.js 4 support. +* Show warning if `caniuse-lite` is old (by Anton Tuzhik). +* Add comma support in config file. + +## 3.2.8 +* Add IE 9-5.5 to dead browsers. +* Remove development configs from npm package. + +## 3.2.7 +* Add Firefox 60 as Firefox ESR. + +## 3.2.6 +* Add Opera Mini 12 to dead browsers. +* Update docs (by Jamie Kyle). + +## 3.2.5 +* Fix excluding Opera Mini and other browsers with `all` version. + +## 3.2.4 +* Resolve shareable config from current working directory. + +## 3.2.3 +* Fix `package.json` config validation for single string case. +* Fix CLI error reporting. + +## 3.2.2 +* Add `package.json` config validation. +* Move project to `browserlist` GitHub organization. + +## 3.2.1 +* Fix error text (by Steve Schrab). + +## 3.2 +* Add `cover 99%` query (by Vasily Fedoseyev). +* Add `cover 99% in US` query (by Vasily Fedoseyev). +* Add `cover 99% in my stats` query (by Vasily Fedoseyev). +* Add `"my stats"` support to `browserlist.coverage()` (by Vasily Fedoseyev). + +## 3.1.2 +* Add more clear error on missed browser version. + +## 3.1.1 +* Fix JSDoc (by Sylvain Pollet-Villard). + +## 3.1 +* Add `ignoreUnknownVersions` option. +* Fix docs (by Pascal Duez). + +## 3.0 “Atelerix sclateri” +* Remove country statistics from client-side build of Browserslist. +* Change `> 1%` to `> 0.5%` in default query. +* Add `not dead` to default query. +* Change default environment to `production` (by Marco Fugaro). +* Add `dead` query support with IE 10 and BlackBerry browser. +* Add multiple environments in one section support (by Evilebot Tnawi). +* Add custom statistics support to `browserlist.coverage()`. +* Fix `path` option check. + +## 2.11.3 +* Fix for `path: undefined` option. + +## 2.11.2 +* Remove Node.js specific code from webpack build. + +## 2.11.1 +* Fix using Browserslist in browser with `path` but without `fs`. + +## 2.11 +* Add `last 2 years` query support (by James Harris). + +## 2.10.2 +* Fix Browserify support. + +## 2.10.1 +* Fix using Browserslist without `process` (by Andrew Patton). + +## 2.10 +* Add `< 1%` and `<= 1%` queries support (by August Kaiser). + +## 2.9.1 +* Fix unknown query on trailing spaces in query. + +## 2.9 +* Add `last Electron versions` and `last Electron major versions` queries + (by Louis Mouhat). + +## 2.8 +* Add `since 2016-03` and `since 2016-03-20` queries support (by Andrew Blick). + +## 2.7 +* Add `since 2016` queries support (by Igor Deryabin). + +## 2.6.1 +* Fix `Path must be a string` error. + +## 2.6 +* By default load config from current directory in CLI tool. + +## 2.5.1 +* Allow `@scope/browserlist-config` config name (by Jamie Connolly). + +## 2.5 +* Add `extends` query (by YellowKirby). + +## 2.4.1 +* Throw error if `package.json` contain `browserlist` instead of `browserslist`. + +## 2.4 +* Add `last n major versions` query (by John Sanders). + +## 2.3.3 +* Fix browsers support. + +## 2.3.2 +* Fix `> 0` query for browsers with one version (by Nikolay Solovyov). + +## 2.3.1 +* Reduce library size. + +## 2.3 +* Add `unreleased versions` and `unreleased Chrome versions` queries. + +## 2.2.2 +* Fix `Path must be a string` error (by Pieter Beulque). + +## 2.2.1 +* Fix security issue with regions dynamic `require`. + +## 2.2 +* Add region usage statistics support (by Clément P). + +## 2.1.5 +* Remove Firefox 45 from Firefox ESR. + +## 2.1.4 +* Use both ESR versions when they actual. + +## 2.1.3 +* Add warning on first exclude query. + +## 2.1.2 +* Fix non-Node.js environments support. + +## 2.1.1 +* Fix CLI arguments parsing. + +## 2.1 +* Add `>= 5%`, `>= 5% in US` and `>= 5% in my stats` queries. + +## 2.0 “Atelerix frontalis” +* `last n versions` returns versions for all browsers, not only main browsers. +* Cache file system operations (by Aarni Koskela). +* Use `caniuse-lite` 1 MB instead of `caniuse-db` 7 MB (by Ben Briggs). +* Add `.browserslistrc` config support. +* Add QQ Browser for Android support. +* Add tests for CLI (by Zhulduz Zhankenova). + +## 1.7.7 +* Update Firefox ESR. + +## 1.7.6 +* Fix Android Chrome selection. + +## 1.7.5 +* Fix combining `not` query with country based statistics. +* Fix `--env` argument in CLI (by Tuure Savuoja). + +## 1.7.4 +* Speed up browser sorting (by Aarni Koskela). + +## 1.7.3 +* Fix config finding when directory was passed to `path` (by Aarni Koskela). + +## 1.7.2 +* Fix config finding algorithm (by Aarni Koskela). + +## 1.7.1 +* Fix unreleased browsers version detection. + +## 1.7 +* Add `--config` and `--env` arguments to CLI (by Jarek Rencz). + +## 1.6 +* Convert Electron version to Chrome (by Kilian Valkhof). +* Fix `0` version mistake in Can I Use data. + +## 1.5.2 +* Fix browser versions ordering (by Marco Massarotto). + +## 1.5.1 +* Fix error on `package.json` and `browserslist` in same directory. + +## 1.5 +* Add `package.json` support (by Stepan Kuzmin). +* Add environments support (by Maksim Semenov and openlibser). +* Add `browserslist-stats.json` file support (by Oleh Aloshkin). +* Add `config` option to CLI (by Evilebot Tnawi). +* Add JSDoc. +* Fix tests on Windows (by Anna Stoliar). +* Don’t set custom usage statistics globally. + +## 1.4 +* Add `defaults` keyword. + +## 1.3.6 +* Add `UCAndroid` alias to `and_uc` (by Evilebot Tnawi). + +## 1.3.5 +* Fix Opera Mini support. Use `op_mini all`. + +## 1.3.4 +* Add space-less `>1%` and `>.5%` syntax support (by Andreas Lind). + +## 1.3.3 +* Clean `0` versions in some country-based requests. + +## 1.3.2 +* Update Firefox ESR. + +## 1.3.1 +* Add Safari TP support. + +## 1.3 +* Add coverage for specific country (by Joshua Wise). + +## 1.2 +* Add `browserslist.coverage()` method. +* Add `--coverage` and `-c` argument to CLI. +* Add `-v` argument support to CLI. +* Better error handling in CLI. + +## 1.1.3 +* Fix jspm support (by Sean Anderson). + +## 1.1.2 +* Fix jspm support (by Sean Anderson). + +## 1.1.1 +* Fix space-less `>10%` and `>10% in my stats` queries. +* Normalize error messages. +* Remove development files from npm package. + +## 1.1 +* Added query against custom browser usage data (by Daniel Rey). + +## 1.0.1 +* Update Firefox ESR (by Rouven Weßling). + +## 1.0 “Atelerix algirus” +* Remove Opera 12.1 from default query. +* Add `not` keyword and exclude browsers by query. +* Add Microsoft Edge support (by Andrey Polischuk). +* Add CLI for debug and non-JS usage (by Luke Horvat). +* Use own class in Browserslist errors. + +## 0.5 +* Add version ranges `IE 6-9` (by Ben Briggs). + +## 0.4 +* Add `config` option and `BROWSERSLIST_CONFIG` environment variable support. +* Add symlink config support. + +## 0.3.3 +* Fix DynJS compatibility (by Nick Howes). + +## 0.3.2 +* Fix joined versions on versions query (by Vincent De Oliveira). + +## 0.3.1 +* Fix global variable leak (by Peter Müller). + +## 0.3 +* Takes queries from `BROWSERSLIST` environment variable. + +## 0.2 +* Return Can I Use joined versions as `ios_saf 7.0-7.1`. + +## 0.1.3 +* Better work with Can I Use joined versions like `ios_saf 7.0-7.1`. +* Browserslist now understands `ios_saf 7.0` or `ios_saf 7`. + +## 0.1.2 +* Do not create global `browserslist` var (by Maxime Thirouin). + +## 0.1.1 +* Sort browsers by name and version. + +## 0.1 “Atelerix albiventris” +* Initial release. diff --git a/node_modules/browserslist/LICENSE b/node_modules/browserslist/LICENSE new file mode 100644 index 0000000..1ae47a2 --- /dev/null +++ b/node_modules/browserslist/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright 2014 Andrey Sitnik + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/browserslist/README.md b/node_modules/browserslist/README.md new file mode 100644 index 0000000..fc5d213 --- /dev/null +++ b/node_modules/browserslist/README.md @@ -0,0 +1,589 @@ +# Browserslist [![Cult Of Martians][cult-img]][cult] + +Browserslist logo by Anton Lovchikov + +The config to share target browsers and Node.js versions between different +front-end tools. It is used in: + +* [Autoprefixer] +* [Babel] +* [postcss-preset-env] +* [eslint-plugin-compat] +* [stylelint-no-unsupported-browser-features] +* [postcss-normalize] +* [obsolete-webpack-plugin] + +All tools will find target browsers automatically, +when you add the following to `package.json`: + +```js + "browserslist": [ + "last 1 version", + "> 1%", + "maintained node versions", + "not dead" + ] +``` + +Or in `.browserslistrc` config: + +```yaml +# Browsers that we support + +last 1 version +> 1% +maintained node versions +not dead +``` + +Developers set versions list in queries like `last 2 version` +to be free from updating versions manually. +Browserslist will use [Can I Use] data for this queries. + +Browserslist will take queries from tool option, +`browserslist` config, `.browserslistrc` config, +`browserslist` section in `package.json` or environment variables. + +[Browserslist Example] shows how every tool uses Browserslist. + +[cult-img]: https://cultofmartians.com/assets/badges/badge.svg +[cult]: https://cultofmartians.com/done.html + + + Sponsored by Evil Martians + + +[stylelint-no-unsupported-browser-features]: https://github.com/ismay/stylelint-no-unsupported-browser-features +[eslint-plugin-compat]: https://github.com/amilajack/eslint-plugin-compat +[Browserslist Example]: https://github.com/browserslist/browserslist-example +[postcss-preset-env]: https://github.com/jonathantneal/postcss-preset-env +[postcss-normalize]: https://github.com/jonathantneal/postcss-normalize +[Autoprefixer]: https://github.com/postcss/autoprefixer +[Can I Use]: https://caniuse.com/ +[Babel]: https://github.com/babel/babel/tree/master/packages/babel-preset-env +[obsolete-webpack-plugin]: https://github.com/ElemeFE/obsolete-webpack-plugin + +## Table of Contents + +1. [Tools](#tools) +2. [Best Practices](#best-practices) +3. [Queries](#queries) +4. [Config File](#config-file) +5. [Shareable Configs](#shareable-configs) +6. [Configuring for Different Environments](#configuring-for-different-environments) +7. [Custom Usage Data](#custom-usage-data) +8. [JS API](#js-api) +9. [Environment Variables](#environment-variables) +10. [Cache](#cache) + +## Tools + +* [`browserslist-ga`] and [`browserslist-ga-export`] download your website + browsers statistics to use it in `> 0.5% in my stats` query. +* [`browserslist-useragent-regexp`] compiles Browserslist query to a RegExp + to test browser useragent. +* [`browserslist-useragent-ruby`] is a Ruby library to checks browser + by user agent string to match Browserslist. +* [`browserslist-browserstack`] runs BrowserStack tests for all browsers + in Browserslist config. +* [`caniuse-api`] returns browsers which support some specific feature. +* Run `npx browserslist` in your project directory to see project’s + target browsers. This CLI tool is built-in and available in any project + with Autoprefixer. + +[`browserslist-useragent-regexp`]: https://github.com/browserslist/browserslist-useragent-regexp +[`browserslist-useragent-ruby`]: https://github.com/browserslist/browserslist-useragent-ruby +[`browserslist-browserstack`]: https://github.com/xeroxinteractive/browserslist-browserstack +[`browserslist-ga-export`]: https://github.com/browserslist/browserslist-ga-export +[`browserslist-useragent`]: https://github.com/pastelsky/browserslist-useragent +[`browserslist-ga`]: https://github.com/browserslist/browserslist-ga +[`caniuse-api`]: https://github.com/Nyalab/caniuse-api + + +## Best Practices + +* Select browsers directly (`last 2 Chrome versions`) only if you are making + a web app for a kiosk with one browser. There are a lot of browsers + on the market. If you are making general web app you should respect + browsers diversity. +* There is a `defaults` query, which gives a reasonable configuration + for most users: + + ```json + "browserslist": [ + "defaults" + ] + ``` + +* If you want to change the default set of browsers we recommend to combine + `last 1 version`, `not dead` with `> 0.2%` (or `> 1% in US`, + `> 1% in my stats`). `last n versions` adds too many dead browsers + and does not add popular old versions. Choosing a percentage above `0.2%` + will in the long run make popular browsers even more popular. We might run + into a monopoly and stagnation situation, as we had with Internet Explorer 6. + Please use this setting with caution. +* Don’t remove browsers just because you don’t know them. Opera Mini has + 100 million users in Africa and it is more popular in the global market + than Microsoft Edge. Chinese QQ Browsers has more market share than Firefox + and desktop Safari combined. + + +## Queries + +Browserslist will use browsers and Node.js versions query +from one of these sources: + +1. `browserslist` key in `package.json` file in current or parent directories. + **We recommend this way.** +2. `.browserslistrc` config file in current or parent directories. +3. `browserslist` config file in current or parent directories. +4. `BROWSERSLIST` environment variable. +5. If the above methods did not produce a valid result + Browserslist will use defaults: + `> 0.5%, last 2 versions, Firefox ESR, not dead`. + + +### Query Composition + +An `or` combiner can use the keyword `or` as well as `,`. +`last 1 version or > 1%` is equal to `last 1 version, > 1%`. + +`and` query combinations are also supported to perform an +intersection of the previous query: `last 1 version and > 1%`. + +There is 3 different ways to combine queries as depicted below. First you start +with a single query and then we combine the queries to get our final list. + +Obviously you can *not* start with a `not` combiner, since there is no left-hand +side query to combine it with. + +| Query combiner type | Illustration | Example | +| ------------------- | :----------: | ------- | +|`or`/`,` combiner
(union) | ![Union of queries](img/union.svg) | `> .5% or last 2 versions`
`> .5%, last 2 versions` | +| `and` combiner
(intersection) | ![intersection of queries](img/intersection.svg) | `> .5% and last 2 versions` | +| `not` combiner
(relative complement) | ![Relative complement of queries](img/complement.svg) | `> .5% and not last 2 versions`
`> .5% or not last 2 versions`
`> .5%, not last 2 versions` | + +_A quick way to test your query is to do `npx browserslist '> 0.5%, not IE 11'` +in your terminal._ + + +### Full List + +You can specify the browser and Node.js versions by queries (case insensitive): + +* `> 5%`: browsers versions selected by global usage statistics. + `>=`, `<` and `<=` work too. +* `> 5% in US`: uses USA usage statistics. It accepts [two-letter country code]. +* `> 5% in alt-AS`: uses Asia region usage statistics. List of all region codes + can be found at [`caniuse-lite/data/regions`]. +* `> 5% in my stats`: uses [custom usage data]. +* `cover 99.5%`: most popular browsers that provide coverage. +* `cover 99.5% in US`: same as above, with [two-letter country code]. +* `cover 99.5% in my stats`: uses [custom usage data]. +* `maintained node versions`: all Node.js versions, which are [still maintained] + by Node.js Foundation. +* `node 10` and `node 10.4`: selects latest Node.js `10.x.x` + or `10.4.x` release. +* `current node`: Node.js version used by Browserslist right now. +* `extends browserslist-config-mycompany`: take queries from + `browserslist-config-mycompany` npm package. +* `ie 6-8`: selects an inclusive range of versions. +* `Firefox > 20`: versions of Firefox newer than 20. + `>=`, `<` and `<=` work too. It also works with Node.js. +* `iOS 7`: the iOS browser version 7 directly. +* `Firefox ESR`: the latest [Firefox ESR] version. +* `PhantomJS 2.1` and `PhantomJS 1.9`: selects Safari versions similar + to PhantomJS runtime. +* `unreleased versions` or `unreleased Chrome versions`: + alpha and beta versions. +* `last 2 major versions` or `last 2 iOS major versions`: + all minor/patch releases of last 2 major versions. +* `since 2015` or `last 2 years`: all versions released since year 2015 + (also `since 2015-03` and `since 2015-03-10`). +* `dead`: browsers without official support or updates for 24 months. + Right now it is `IE 10`, `IE_Mob 10`, `BlackBerry 10`, `BlackBerry 7`, + `Samsung 4` and `OperaMobile 12.1`. +* `last 2 versions`: the last 2 versions for *each* browser. +* `last 2 Chrome versions`: the last 2 versions of Chrome browser. +* `defaults`: Browserslist’s default browsers + (`> 0.5%, last 2 versions, Firefox ESR, not dead`). +* `not ie <= 8`: exclude browsers selected by previous queries. + +You can add `not ` to any query. + +[`caniuse-lite/data/regions`]: https://github.com/ben-eb/caniuse-lite/tree/master/data/regions +[two-letter country code]: https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements +[custom usage data]: #custom-usage-data +[still maintained]: https://github.com/nodejs/Release +[Can I Use]: https://caniuse.com/ + + +### Debug + +Run `npx browserslist` in project directory to see what browsers was selected +by your queries. + +```sh +$ npx browserslist +and_chr 61 +and_ff 56 +and_qq 1.2 +and_uc 11.4 +android 56 +baidu 7.12 +bb 10 +chrome 62 +edge 16 +firefox 56 +ios_saf 11 +opera 48 +safari 11 +samsung 5 +``` + + +### Browsers + +Names are case insensitive: + +* `Android` for Android WebView. +* `Baidu` for Baidu Browser. +* `BlackBerry` or `bb` for Blackberry browser. +* `Chrome` for Google Chrome. +* `ChromeAndroid` or `and_chr` for Chrome for Android +* `Edge` for Microsoft Edge. +* `Electron` for Electron framework. It will be converted to Chrome version. +* `Explorer` or `ie` for Internet Explorer. +* `ExplorerMobile` or `ie_mob` for Internet Explorer Mobile. +* `Firefox` or `ff` for Mozilla Firefox. +* `FirefoxAndroid` or `and_ff` for Firefox for Android. +* `iOS` or `ios_saf` for iOS Safari. +* `Node` for Node.js. +* `Opera` for Opera. +* `OperaMini` or `op_mini` for Opera Mini. +* `OperaMobile` or `op_mob` for Opera Mobile. +* `QQAndroid` or `and_qq` for QQ Browser for Android. +* `Safari` for desktop Safari. +* `Samsung` for Samsung Internet. +* `UCAndroid` or `and_uc` for UC Browser for Android. +* `kaios` for KaiOS Browser. + + +## Config File + +### `package.json` + +If you want to reduce config files in project root, you can specify +browsers in `package.json` with `browserslist` key: + +```json +{ + "private": true, + "dependencies": { + "autoprefixer": "^6.5.4" + }, + "browserslist": [ + "last 1 version", + "> 1%", + "IE 10" + ] +} +``` + + +### `.browserslistrc` + +Separated Browserslist config should be named `.browserslistrc` +and have browsers queries split by a new line. Comments starts with `#` symbol: + +```yaml +# Browsers that we support + +last 1 version +> 1% +IE 10 # sorry +``` + +Browserslist will check config in every directory in `path`. +So, if tool process `app/styles/main.css`, you can put config to root, +`app/` or `app/styles`. + +You can specify direct path in `BROWSERSLIST_CONFIG` environment variables. + + +## Shareable Configs + +You can use the following query to reference an exported Browserslist config +from another package: + +```json + "browserslist": [ + "extends browserslist-config-mycompany" + ] +``` + +For security reasons, external configuration only supports packages that have +the `browserslist-config-` prefix. npm scoped packages are also supported, by +naming or prefixing the module with `@scope/browserslist-config`, such as +`@scope/browserslist-config` or `@scope/browserslist-config-mycompany`. + +If you don’t accept Browserslist queries from users, you can disable the +validation by using the `dangerousExtend` option: + +```js +browserslist(queries, { path, dangerousExtend: true }) +``` + +Because this uses `npm`'s resolution, you can also reference specific files +in a package: + +```json + "browserslist": [ + "extends browserslist-config-mycompany/desktop", + "extends browserslist-config-mycompany/mobile" + ] +``` + +When writing a shared Browserslist package, just export an array. +`browserslist-config-mycompany/index.js`: + +```js +module.exports = [ + 'last 1 version', + '> 1%', + 'ie 10' +] +``` + + +## Configuring for Different Environments + +You can also specify different browser queries for various environments. +Browserslist will choose query according to `BROWSERSLIST_ENV` or `NODE_ENV` +variables. If none of them is declared, Browserslist will firstly look +for `production` queries and then use defaults. + +In `package.json`: + +```js + "browserslist": { + "production": [ + "> 1%", + "ie 10" + ], + "modern": [ + "last 1 chrome version", + "last 1 firefox version" + ], + "ssr": [ + "node 12" + ] + } +``` + +In `.browserslistrc` config: + +```ini +[production] +> 1% +ie 10 + +[modern] +last 1 chrome version +last 1 firefox version + +[ssr] +node 12 +``` + + +## Custom Usage Data + +If you have a website, you can query against the usage statistics of your site. +[`browserslist-ga`] will ask access to Google Analytics and then generate +`browserslist-stats.json`: + +``` +npx browserslist-ga +``` + +Or you can use [`browserslist-ga-export`] to convert Google Analytics data without giving a password for Google account. + +You can generate usage statistics file by any other method. File format should +be like: + +```js +{ + "ie": { + "6": 0.01, + "7": 0.4, + "8": 1.5 + }, + "chrome": { + … + }, + … +} +``` + +Note that you can query against your custom usage data while also querying +against global or regional data. For example, the query +`> 1% in my stats, > 5% in US, 10%` is permitted. + +[`browserslist-ga-export`]: https://github.com/browserslist/browserslist-ga-export +[`browserslist-ga`]: https://github.com/browserslist/browserslist-ga +[Can I Use]: https://caniuse.com/ + + +## JS API + +```js +const browserslist = require('browserslist') + +// Your CSS/JS build tool code +function process (source, opts) { + const browsers = browserslist(opts.overrideBrowserslist, { + stats: opts.stats, + path: opts.file, + env: opts.env + }) + // Your code to add features for selected browsers +} +``` + +Queries can be a string `"> 1%, IE 10"` +or an array `['> 1%', 'IE 10']`. + +If a query is missing, Browserslist will look for a config file. +You can provide a `path` option (that can be a file) to find the config file +relatively to it. + +Options: + +* `path`: file or a directory path to look for config file. Default is `.`. +* `env`: what environment section use from config. Default is `production`. +* `stats`: custom usage statistics data. +* `config`: path to config if you want to set it manually. +* `ignoreUnknownVersions`: do not throw on direct query (like `ie 12`). + Default is `false.` +* `dangerousExtend`: Disable security checks for `extend` query. + Default is `false.` +* `mobileToDesktop`: Use desktop browsers if Can I Use doesn’t have data + about this mobile version. For instance, Browserslist will return + `chrome 20` on `and_chr 20` query (Can I Use has only data only about + latest versions of mobile browsers). Default is `false`. + +For non-JS environment and debug purpose you can use CLI tool: + +```sh +browserslist "> 1%, IE 10" +``` + +You can get total users coverage for selected browsers by JS API: + +```js +browserslist.coverage(browserslist('> 1%')) +//=> 81.4 +``` + +```js +browserslist.coverage(browserslist('> 1% in US'), 'US') +//=> 83.1 +``` + +```js +browserslist.coverage(browserslist('> 1% in my stats'), 'my stats') +//=> 83.1 +``` + +```js +browserslist.coverage(browserslist('> 1% in my stats', { stats }), stats) +//=> 82.2 +``` + +Or by CLI: + +```sh +$ browserslist --coverage "> 1%" +These browsers account for 81.4% of all users globally +``` + +```sh +$ browserslist --coverage=US "> 1% in US" +These browsers account for 83.1% of all users in the US +``` + +```sh +$ browserslist --coverage "> 1% in my stats" +These browsers account for 83.1% of all users in custom statistics +``` + +```sh +$ browserslist --coverage "> 1% in my stats" --stats=./stats.json +These browsers account for 83.1% of all users in custom statistics +``` + + +## Environment Variables + +If some tool use Browserslist inside, you can change browsers settings +by [environment variables]: + +* `BROWSERSLIST` with browsers queries. + + ```sh + BROWSERSLIST="> 5%" gulp css + ``` + +* `BROWSERSLIST_CONFIG` with path to config file. + + ```sh + BROWSERSLIST_CONFIG=./config/browserslist gulp css + ``` + +* `BROWSERSLIST_ENV` with environments string. + + ```sh + BROWSERSLIST_ENV="development" gulp css + ``` + +* `BROWSERSLIST_STATS` with path to the custom usage data + for `> 1% in my stats` query. + + ```sh + BROWSERSLIST_STATS=./config/usage_data.json gulp css + ``` + +* `BROWSERSLIST_DISABLE_CACHE` if you want to disable config reading cache. + + ```sh + BROWSERSLIST_DISABLE_CACHE=1 gulp css + ``` + +[environment variables]: https://en.wikipedia.org/wiki/Environment_variable + + +## Cache + +Browserslist caches the configuration it reads from `package.json` and +`browserslist` files, as well as knowledge about the existence of files, +for the duration of the hosting process. + +To clear these caches, use: + +```js +browserslist.clearCaches() +``` + +To disable the caching altogether, set the `BROWSERSLIST_DISABLE_CACHE` +environment variable. + + +## Security Contact + +To report a security vulnerability, please use the [Tidelift security contact]. +Tidelift will coordinate the fix and disclosure. + +[Tidelift security contact]: https://tidelift.com/security diff --git a/node_modules/browserslist/browser.js b/node_modules/browserslist/browser.js new file mode 100644 index 0000000..77a217a --- /dev/null +++ b/node_modules/browserslist/browser.js @@ -0,0 +1,41 @@ +var BrowserslistError = require('./error') + +function noop () { } + +module.exports = { + loadQueries: function loadQueries () { + throw new BrowserslistError( + 'Sharable configs are not supported in client-side build of Browserslist') + }, + + getStat: function getStat (opts) { + return opts.stats + }, + + loadConfig: function loadConfig (opts) { + if (opts.config) { + throw new BrowserslistError( + 'Browserslist config are not supported in client-side build') + } + }, + + loadCountry: function loadCountry () { + throw new BrowserslistError( + 'Country statistics is not supported ' + + 'in client-side build of Browserslist') + }, + + currentNode: function currentNode (resolve, context) { + return resolve(['maintained node versions'], context)[0] + }, + + parseConfig: noop, + + readConfig: noop, + + findConfig: noop, + + clearCaches: noop, + + oldDataWarning: noop +} diff --git a/node_modules/browserslist/cli.js b/node_modules/browserslist/cli.js new file mode 100755 index 0000000..d58f9c8 --- /dev/null +++ b/node_modules/browserslist/cli.js @@ -0,0 +1,135 @@ +#!/usr/bin/env node + +var fs = require('fs') + +var browserslist = require('./') +var pkg = require('./package.json') +var args = process.argv.slice(2) + +var USAGE = 'Usage:\n' + + ' ' + pkg.name + '\n' + + ' ' + pkg.name + ' "QUERIES"\n' + + ' ' + pkg.name + ' --json "QUERIES"\n' + + ' ' + pkg.name + ' --config="path/to/browserlist/file"\n' + + ' ' + pkg.name + ' --coverage "QUERIES"\n' + + ' ' + pkg.name + ' --coverage=US "QUERIES"\n' + + ' ' + pkg.name + ' --coverage=US,RU,global "QUERIES"\n' + + ' ' + pkg.name + ' --env="environment name defined in config"\n' + + ' ' + pkg.name + ' --stats="path/to/browserlist/stats/file"' + +function isArg (arg) { + return args.some(function (str) { + return str === arg || str.indexOf(arg + '=') === 0 + }) +} + +function error (msg) { + process.stderr.write(pkg.name + ': ' + msg + '\n') + process.exit(1) +} + +if (isArg('--help') || isArg('-h')) { + process.stdout.write(pkg.description + '.\n\n' + USAGE + '\n') +} else if (isArg('--version') || isArg('-v')) { + process.stdout.write(pkg.name + ' ' + pkg.version + '\n') +} else { + var mode = 'browsers' + var opts = { } + var queries + var areas + + for (var i = 0; i < args.length; i++) { + if (args[i][0] !== '-') { + queries = args[i].replace(/^["']|["']$/g, '') + continue + } + + var arg = args[i].split('=') + var name = arg[0] + var value = arg[1] + + if (value) value = value.replace(/^["']|["']$/g, '') + + if (name === '--config' || name === '-b') { + opts.config = value + } else if (name === '--env' || name === '-e') { + opts.env = value + } else if (name === '--stats' || name === '-s') { + opts.stats = value + } else if (name === '--coverage' || name === '-c') { + if (mode !== 'json') mode = 'coverage' + if (value) { + areas = value.split(',') + } else { + areas = ['global'] + } + } else if (name === '--json') { + mode = 'json' + } else { + error('Unknown arguments ' + args[i] + '.\n\n' + USAGE) + } + } + + var browsers + try { + browsers = browserslist(queries, opts) + } catch (e) { + if (e.name === 'BrowserslistError') { + error(e.message) + } else { + throw e + } + } + + var coverage + if (mode === 'browsers') { + browsers.forEach(function (browser) { + process.stdout.write(browser + '\n') + }) + } else if (areas) { + coverage = areas.map(function (area) { + var stats + if (area !== 'global') { + stats = area + } else if (opts.stats) { + stats = JSON.parse(fs.readFileSync(opts.stats)) + } + var result = browserslist.coverage(browsers, stats) + var round = Math.round(result * 100) / 100.0 + + return [area, round] + }) + + if (mode === 'coverage') { + var prefix = 'These browsers account for ' + process.stdout.write(prefix) + coverage.forEach(function (data, index) { + var area = data[0] + var round = data[1] + var end = 'globally' + if (area && area !== 'global') { + end = 'in the ' + area.toUpperCase() + } else if (opts.stats) { + end = 'in custom statistics' + } + + if (index !== 0) { + process.stdout.write(prefix.replace(/./g, ' ')) + } + + process.stdout.write(round + '% of all users ' + end + '\n') + }) + } + } + + if (mode === 'json') { + var data = { browsers: browsers } + if (coverage) { + data.coverage = coverage.reduce(function (object, j) { + object[j[0]] = j[1] + return object + }, { }) + } + process.stdout.write(JSON.stringify(data, null, ' ') + '\n') + } +} diff --git a/node_modules/browserslist/error.js b/node_modules/browserslist/error.js new file mode 100644 index 0000000..b3bc0fe --- /dev/null +++ b/node_modules/browserslist/error.js @@ -0,0 +1,12 @@ +function BrowserslistError (message) { + this.name = 'BrowserslistError' + this.message = message + this.browserslist = true + if (Error.captureStackTrace) { + Error.captureStackTrace(this, BrowserslistError) + } +} + +BrowserslistError.prototype = Error.prototype + +module.exports = BrowserslistError diff --git a/node_modules/browserslist/index.js b/node_modules/browserslist/index.js new file mode 100644 index 0000000..dd4dfea --- /dev/null +++ b/node_modules/browserslist/index.js @@ -0,0 +1,996 @@ +var jsReleases = require('node-releases/data/processed/envs.json') +var agents = require('caniuse-lite/dist/unpacker/agents').agents +var jsEOL = require('node-releases/data/release-schedule/release-schedule.json') +var path = require('path') +var e2c = require('electron-to-chromium/versions') + +var BrowserslistError = require('./error') +var env = require('./node') // Will load browser.js in webpack + +var FLOAT_RANGE = /^\d+(\.\d+)?(-\d+(\.\d+)?)*$/ +var YEAR = 365.259641 * 24 * 60 * 60 * 1000 + +var QUERY_OR = 1 +var QUERY_AND = 2 + +function isVersionsMatch (versionA, versionB) { + return (versionA + '.').indexOf(versionB + '.') === 0 +} + +function isEolReleased (name) { + var version = name.slice(1) + return jsReleases.some(function (i) { + return isVersionsMatch(i.version, version) + }) +} + +function normalize (versions) { + return versions.filter(function (version) { + return typeof version === 'string' + }) +} + +function normalizeElectron (version) { + var versionToUse = version + if (version.split('.').length === 3) { + versionToUse = version + .split('.') + .slice(0, -1) + .join('.') + } + return versionToUse +} + +function nameMapper (name) { + return function mapName (version) { + return name + ' ' + version + } +} + +function getMajor (version) { + return parseInt(version.split('.')[0]) +} + +function getMajorVersions (released, number) { + if (released.length === 0) return [] + var minimum = getMajor(released[released.length - 1]) - parseInt(number) + 1 + var selected = [] + for (var i = released.length - 1; i >= 0; i--) { + if (minimum > getMajor(released[i])) break + selected.unshift(released[i]) + } + return selected +} + +function uniq (array) { + var filtered = [] + for (var i = 0; i < array.length; i++) { + if (filtered.indexOf(array[i]) === -1) filtered.push(array[i]) + } + return filtered +} + +// Helpers + +function fillUsage (result, name, data) { + for (var i in data) { + result[name + ' ' + i] = data[i] + } +} + +function generateFilter (sign, version) { + version = parseFloat(version) + if (sign === '>') { + return function (v) { + return parseFloat(v) > version + } + } else if (sign === '>=') { + return function (v) { + return parseFloat(v) >= version + } + } else if (sign === '<') { + return function (v) { + return parseFloat(v) < version + } + } else { + return function (v) { + return parseFloat(v) <= version + } + } +} + +function generateSemverFilter (sign, version) { + version = version.split('.').map(parseSimpleInt) + version[1] = version[1] || 0 + version[2] = version[2] || 0 + if (sign === '>') { + return function (v) { + v = v.split('.').map(parseSimpleInt) + return compareSemver(v, version) > 0 + } + } else if (sign === '>=') { + return function (v) { + v = v.split('.').map(parseSimpleInt) + return compareSemver(v, version) >= 0 + } + } else if (sign === '<') { + return function (v) { + v = v.split('.').map(parseSimpleInt) + return compareSemver(version, v) > 0 + } + } else { + return function (v) { + v = v.split('.').map(parseSimpleInt) + return compareSemver(version, v) >= 0 + } + } +} + +function parseSimpleInt (x) { + return parseInt(x) +} + +function compare (a, b) { + if (a < b) return -1 + if (a > b) return +1 + return 0 +} + +function compareSemver (a, b) { + return ( + compare(a[0], b[0]) || + compare(a[1], b[1]) || + compare(a[2], b[2]) + ) +} + +function resolveVersion (data, version) { + if (data.versions.indexOf(version) !== -1) { + return version + } else if (browserslist.versionAliases[data.name][version]) { + return browserslist.versionAliases[data.name][version] + } else { + return false + } +} + +function normalizeVersion (data, version, context) { + var resolved = resolveVersion(data, version) + if ( + !resolved && + context.mobileToDesktop && + browserslist.desktopNames[data.name] + ) { + var alias = checkName(browserslist.desktopNames[data.name]) + resolved = resolveVersion(alias, version) + } + if (resolved) { + return resolved + } else if (data.versions.length === 1) { + return data.versions[0] + } else { + return false + } +} + +function filterByYear (since) { + since = since / 1000 + return Object.keys(agents).reduce(function (selected, name) { + var data = byName(name) + if (!data) return selected + var versions = Object.keys(data.releaseDate).filter(function (v) { + return data.releaseDate[v] >= since + }) + return selected.concat(versions.map(nameMapper(data.name))) + }, []) +} + +function byName (name) { + name = name.toLowerCase() + name = browserslist.aliases[name] || name + return browserslist.data[name] +} + +function checkName (name) { + var data = byName(name) + if (!data) throw new BrowserslistError('Unknown browser ' + name) + return data +} + +function unknownQuery (query) { + return new BrowserslistError( + 'Unknown browser query `' + query + '`. ' + + 'Maybe you are using old Browserslist or made typo in query.' + ) +} + +function filterAndroid (list, versions) { + var released = browserslist.data.android.released + var firstEvergreen = 37 + var last = released[released.length - 1] + var diff = last - firstEvergreen - versions // First Android Evergreen + if (diff > 0) { + return list.slice(-1) + } else { + return list.slice(diff - 1) + } +} + +/** + * Resolves queries into a browser list. + * @param {string|string[]} queries Queries to combine. + * Either an array of queries or a long string of queries. + * @param {object} [context] Optional arguments to + * the select function in `queries`. + * @returns {string[]} A list of browsers + */ +function resolve (queries, context) { + if (Array.isArray(queries)) { + queries = flatten(queries.map(parse)) + } else { + queries = parse(queries) + } + + return queries.reduce(function (result, query, index) { + var selection = query.queryString + + var isExclude = selection.indexOf('not ') === 0 + if (isExclude) { + if (index === 0) { + throw new BrowserslistError( + 'Write any browsers query (for instance, `defaults`) ' + + 'before `' + selection + '`') + } + selection = selection.slice(4) + } + + for (var i = 0; i < QUERIES.length; i++) { + var type = QUERIES[i] + var match = selection.match(type.regexp) + if (match) { + var args = [context].concat(match.slice(1)) + var array = type.select.apply(browserslist, args).map(function (j) { + var parts = j.split(' ') + if (parts[1] === '0') { + return parts[0] + ' ' + byName(parts[0]).versions[0] + } else { + return j + } + }) + + switch (query.type) { + case QUERY_AND: + if (isExclude) { + return result.filter(function (j) { + return array.indexOf(j) === -1 + }) + } else { + return result.filter(function (j) { + return array.indexOf(j) !== -1 + }) + } + case QUERY_OR: + default: + if (isExclude) { + var filter = { } + array.forEach(function (j) { + filter[j] = true + }) + return result.filter(function (j) { + return !filter[j] + }) + } + return result.concat(array) + } + } + } + + throw unknownQuery(selection) + }, []) +} + +/** + * Return array of browsers by selection queries. + * + * @param {(string|string[])} [queries=browserslist.defaults] Browser queries. + * @param {object} [opts] Options. + * @param {string} [opts.path="."] Path to processed file. + * It will be used to find config files. + * @param {string} [opts.env="production"] Processing environment. + * It will be used to take right + * queries from config file. + * @param {string} [opts.config] Path to config file with queries. + * @param {object} [opts.stats] Custom browser usage statistics + * for "> 1% in my stats" query. + * @param {boolean} [opts.ignoreUnknownVersions=false] Do not throw on unknown + * version in direct query. + * @param {boolean} [opts.dangerousExtend] Disable security checks + * for extend query. + * @param {boolean} [opts.mobileToDesktop] Alias mobile browsers to the desktop + * version when Can I Use doesn't have + * data about the specified version. + * @returns {string[]} Array with browser names in Can I Use. + * + * @example + * browserslist('IE >= 10, IE 8') //=> ['ie 11', 'ie 10', 'ie 8'] + */ +function browserslist (queries, opts) { + if (typeof opts === 'undefined') opts = { } + + if (typeof opts.path === 'undefined') { + opts.path = path.resolve ? path.resolve('.') : '.' + } + + if (typeof queries === 'undefined' || queries === null) { + var config = browserslist.loadConfig(opts) + if (config) { + queries = config + } else { + queries = browserslist.defaults + } + } + + if (!(typeof queries === 'string' || Array.isArray(queries))) { + throw new BrowserslistError( + 'Browser queries must be an array or string. Got ' + typeof queries + '.') + } + + var context = { + ignoreUnknownVersions: opts.ignoreUnknownVersions, + dangerousExtend: opts.dangerousExtend, + mobileToDesktop: opts.mobileToDesktop + } + + env.oldDataWarning(browserslist.data) + var stats = env.getStat(opts, browserslist.data) + if (stats) { + context.customUsage = { } + for (var browser in stats) { + fillUsage(context.customUsage, browser, stats[browser]) + } + } + + var result = resolve(queries, context).sort(function (name1, name2) { + name1 = name1.split(' ') + name2 = name2.split(' ') + if (name1[0] === name2[0]) { + if (FLOAT_RANGE.test(name1[1]) && FLOAT_RANGE.test(name2[1])) { + return parseFloat(name2[1]) - parseFloat(name1[1]) + } else { + return compare(name2[1], name1[1]) + } + } else { + return compare(name1[0], name2[0]) + } + }) + + return uniq(result) +} + +function parse (queries) { + var qs = [] + do { + queries = doMatch(queries, qs) + } while (queries) + return qs +} + +function doMatch (string, qs) { + var or = /^(?:,\s*|\s+OR\s+)(.*)/i + var and = /^\s+AND\s+(.*)/i + + return find(string, function (parsed, n, max) { + if (and.test(parsed)) { + qs.unshift({ type: QUERY_AND, queryString: parsed.match(and)[1] }) + return true + } else if (or.test(parsed)) { + qs.unshift({ type: QUERY_OR, queryString: parsed.match(or)[1] }) + return true + } else if (n === max) { + qs.unshift({ type: QUERY_OR, queryString: parsed.trim() }) + return true + } + return false + }) +} + +function find (string, predicate) { + for (var n = 1, max = string.length; n <= max; n++) { + var parsed = string.substr(-n, n) + if (predicate(parsed, n, max)) { + return string.slice(0, -n) + } + } + return '' +} + +function flatten (array) { + if (!Array.isArray(array)) return [array] + return array.reduce(function (a, b) { + return a.concat(flatten(b)) + }, []) +} + +// Will be filled by Can I Use data below +browserslist.data = { } +browserslist.usage = { + global: { }, + custom: null +} + +// Default browsers query +browserslist.defaults = [ + '> 0.5%', + 'last 2 versions', + 'Firefox ESR', + 'not dead' +] + +// Browser names aliases +browserslist.aliases = { + fx: 'firefox', + ff: 'firefox', + ios: 'ios_saf', + explorer: 'ie', + blackberry: 'bb', + explorermobile: 'ie_mob', + operamini: 'op_mini', + operamobile: 'op_mob', + chromeandroid: 'and_chr', + firefoxandroid: 'and_ff', + ucandroid: 'and_uc', + qqandroid: 'and_qq' +} + +// Can I Use only provides a few versions for some browsers (e.g. and_chr). +// Fallback to a similar browser for unknown versions +browserslist.desktopNames = { + and_chr: 'chrome', + and_ff: 'firefox', + ie_mob: 'ie', + op_mob: 'opera' +} + +// Aliases to work with joined versions like `ios_saf 7.0-7.1` +browserslist.versionAliases = { } + +browserslist.clearCaches = env.clearCaches +browserslist.parseConfig = env.parseConfig +browserslist.readConfig = env.readConfig +browserslist.findConfig = env.findConfig +browserslist.loadConfig = env.loadConfig + +/** + * Return browsers market coverage. + * + * @param {string[]} browsers Browsers names in Can I Use. + * @param {string|object} [stats="global"] Which statistics should be used. + * Country code or custom statistics. + * Pass `"my stats"` to load statistics + * from Browserslist files. + * + * @return {number} Total market coverage for all selected browsers. + * + * @example + * browserslist.coverage(browserslist('> 1% in US'), 'US') //=> 83.1 + */ +browserslist.coverage = function (browsers, stats) { + var data + if (typeof stats === 'undefined') { + data = browserslist.usage.global + } else if (stats === 'my stats') { + var opts = {} + opts.path = path.resolve ? path.resolve('.') : '.' + var customStats = env.getStat(opts) + if (!customStats) { + throw new BrowserslistError('Custom usage statistics was not provided') + } + data = {} + for (var browser in customStats) { + fillUsage(data, browser, customStats[browser]) + } + } else if (typeof stats === 'string') { + if (stats.length > 2) { + stats = stats.toLowerCase() + } else { + stats = stats.toUpperCase() + } + env.loadCountry(browserslist.usage, stats) + data = browserslist.usage[stats] + } else { + if ('dataByBrowser' in stats) { + stats = stats.dataByBrowser + } + data = { } + for (var name in stats) { + for (var version in stats[name]) { + data[name + ' ' + version] = stats[name][version] + } + } + } + + return browsers.reduce(function (all, i) { + var usage = data[i] + if (usage === undefined) { + usage = data[i.replace(/ \S+$/, ' 0')] + } + return all + (usage || 0) + }, 0) +} + +var QUERIES = [ + { + regexp: /^last\s+(\d+)\s+major\s+versions?$/i, + select: function (context, versions) { + return Object.keys(agents).reduce(function (selected, name) { + var data = byName(name) + if (!data) return selected + var list = getMajorVersions(data.released, versions) + list = list.map(nameMapper(data.name)) + if (data.name === 'android') list = filterAndroid(list, versions) + return selected.concat(list) + }, []) + } + }, + { + regexp: /^last\s+(\d+)\s+versions?$/i, + select: function (context, versions) { + return Object.keys(agents).reduce(function (selected, name) { + var data = byName(name) + if (!data) return selected + var list = data.released.slice(-versions) + list = list.map(nameMapper(data.name)) + if (data.name === 'android') list = filterAndroid(list, versions) + return selected.concat(list) + }, []) + } + }, + { + regexp: /^last\s+(\d+)\s+electron\s+major\s+versions?$/i, + select: function (context, versions) { + var validVersions = getMajorVersions(Object.keys(e2c).reverse(), versions) + return validVersions.map(function (i) { + return 'chrome ' + e2c[i] + }) + } + }, + { + regexp: /^last\s+(\d+)\s+(\w+)\s+major\s+versions?$/i, + select: function (context, versions, name) { + var data = checkName(name) + var validVersions = getMajorVersions(data.released, versions) + var list = validVersions.map(nameMapper(data.name)) + if (data.name === 'android') list = filterAndroid(list, versions) + return list + } + }, + { + regexp: /^last\s+(\d+)\s+electron\s+versions?$/i, + select: function (context, versions) { + return Object.keys(e2c).reverse().slice(-versions).map(function (i) { + return 'chrome ' + e2c[i] + }) + } + }, + { + regexp: /^last\s+(\d+)\s+(\w+)\s+versions?$/i, + select: function (context, versions, name) { + var data = checkName(name) + var list = data.released.slice(-versions).map(nameMapper(data.name)) + if (data.name === 'android') list = filterAndroid(list, versions) + return list + } + }, + { + regexp: /^unreleased\s+versions$/i, + select: function () { + return Object.keys(agents).reduce(function (selected, name) { + var data = byName(name) + if (!data) return selected + var list = data.versions.filter(function (v) { + return data.released.indexOf(v) === -1 + }) + list = list.map(nameMapper(data.name)) + return selected.concat(list) + }, []) + } + }, + { + regexp: /^unreleased\s+electron\s+versions?$/i, + select: function () { + return [] + } + }, + { + regexp: /^unreleased\s+(\w+)\s+versions?$/i, + select: function (context, name) { + var data = checkName(name) + return data.versions.filter(function (v) { + return data.released.indexOf(v) === -1 + }).map(nameMapper(data.name)) + } + }, + { + regexp: /^last\s+(\d*.?\d+)\s+years?$/i, + select: function (context, years) { + return filterByYear(Date.now() - YEAR * years) + } + }, + { + regexp: /^since (\d+)(?:-(\d+))?(?:-(\d+))?$/i, + select: function (context, year, month, date) { + year = parseInt(year) + month = parseInt(month || '01') - 1 + date = parseInt(date || '01') + return filterByYear(Date.UTC(year, month, date, 0, 0, 0)) + } + }, + { + regexp: /^(>=?|<=?)\s*(\d*\.?\d+)%$/, + select: function (context, sign, popularity) { + popularity = parseFloat(popularity) + var usage = browserslist.usage.global + return Object.keys(usage).reduce(function (result, version) { + if (sign === '>') { + if (usage[version] > popularity) { + result.push(version) + } + } else if (sign === '<') { + if (usage[version] < popularity) { + result.push(version) + } + } else if (sign === '<=') { + if (usage[version] <= popularity) { + result.push(version) + } + } else if (usage[version] >= popularity) { + result.push(version) + } + return result + }, []) + } + }, + { + regexp: /^(>=?|<=?)\s*(\d*\.?\d+)%\s+in\s+my\s+stats$/, + select: function (context, sign, popularity) { + popularity = parseFloat(popularity) + if (!context.customUsage) { + throw new BrowserslistError('Custom usage statistics was not provided') + } + var usage = context.customUsage + return Object.keys(usage).reduce(function (result, version) { + if (sign === '>') { + if (usage[version] > popularity) { + result.push(version) + } + } else if (sign === '<') { + if (usage[version] < popularity) { + result.push(version) + } + } else if (sign === '<=') { + if (usage[version] <= popularity) { + result.push(version) + } + } else if (usage[version] >= popularity) { + result.push(version) + } + return result + }, []) + } + }, + { + regexp: /^(>=?|<=?)\s*(\d*\.?\d+)%\s+in\s+((alt-)?\w\w)$/, + select: function (context, sign, popularity, place) { + popularity = parseFloat(popularity) + if (place.length === 2) { + place = place.toUpperCase() + } else { + place = place.toLowerCase() + } + env.loadCountry(browserslist.usage, place) + var usage = browserslist.usage[place] + return Object.keys(usage).reduce(function (result, version) { + if (sign === '>') { + if (usage[version] > popularity) { + result.push(version) + } + } else if (sign === '<') { + if (usage[version] < popularity) { + result.push(version) + } + } else if (sign === '<=') { + if (usage[version] <= popularity) { + result.push(version) + } + } else if (usage[version] >= popularity) { + result.push(version) + } + return result + }, []) + } + }, + { + regexp: /^cover\s+(\d*\.?\d+)%(\s+in\s+(my\s+stats|(alt-)?\w\w))?$/, + select: function (context, coverage, statMode) { + coverage = parseFloat(coverage) + var usage = browserslist.usage.global + if (statMode) { + if (statMode.match(/^\s+in\s+my\s+stats$/)) { + if (!context.customUsage) { + throw new BrowserslistError( + 'Custom usage statistics was not provided' + ) + } + usage = context.customUsage + } else { + var match = statMode.match(/\s+in\s+((alt-)?\w\w)/) + var place = match[1] + if (place.length === 2) { + place = place.toUpperCase() + } else { + place = place.toLowerCase() + } + env.loadCountry(browserslist.usage, place) + usage = browserslist.usage[place] + } + } + var versions = Object.keys(usage).sort(function (a, b) { + return usage[b] - usage[a] + }) + var coveraged = 0 + var result = [] + var version + for (var i = 0; i <= versions.length; i++) { + version = versions[i] + if (usage[version] === 0) break + coveraged += usage[version] + result.push(version) + if (coveraged >= coverage) break + } + return result + } + }, + { + regexp: /^electron\s+([\d.]+)\s*-\s*([\d.]+)$/i, + select: function (context, from, to) { + var fromToUse = normalizeElectron(from) + var toToUse = normalizeElectron(to) + if (!e2c[fromToUse]) { + throw new BrowserslistError('Unknown version ' + from + ' of electron') + } + if (!e2c[toToUse]) { + throw new BrowserslistError('Unknown version ' + to + ' of electron') + } + from = parseFloat(from) + to = parseFloat(to) + return Object.keys(e2c).filter(function (i) { + var parsed = parseFloat(i) + return parsed >= from && parsed <= to + }).map(function (i) { + return 'chrome ' + e2c[i] + }) + } + }, + { + regexp: /^(\w+)\s+([\d.]+)\s*-\s*([\d.]+)$/i, + select: function (context, name, from, to) { + var data = checkName(name) + from = parseFloat(normalizeVersion(data, from, context) || from) + to = parseFloat(normalizeVersion(data, to, context) || to) + function filter (v) { + var parsed = parseFloat(v) + return parsed >= from && parsed <= to + } + return data.released.filter(filter).map(nameMapper(data.name)) + } + }, + { + regexp: /^electron\s*(>=?|<=?)\s*([\d.]+)$/i, + select: function (context, sign, version) { + var versionToUse = normalizeElectron(version) + return Object.keys(e2c) + .filter(generateFilter(sign, versionToUse)) + .map(function (i) { + return 'chrome ' + e2c[i] + }) + } + }, + { + regexp: /^node\s*(>=?|<=?)\s*([\d.]+)$/i, + select: function (context, sign, version) { + var nodeVersions = jsReleases.filter(function (i) { + return i.name === 'nodejs' + }).map(function (i) { + return i.version + }) + return nodeVersions + .filter(generateSemverFilter(sign, version)) + .map(function (v) { + return 'node ' + v + }) + } + }, + { + regexp: /^(\w+)\s*(>=?|<=?)\s*([\d.]+)$/, + select: function (context, name, sign, version) { + var data = checkName(name) + var alias = browserslist.versionAliases[data.name][version] + if (alias) { + version = alias + } + return data.released + .filter(generateFilter(sign, version)) + .map(function (v) { + return data.name + ' ' + v + }) + } + }, + { + regexp: /^(firefox|ff|fx)\s+esr$/i, + select: function () { + return ['firefox 68', 'firefox 60'] + } + }, + { + regexp: /(operamini|op_mini)\s+all/i, + select: function () { + return ['op_mini all'] + } + }, + { + regexp: /^electron\s+([\d.]+)$/i, + select: function (context, version) { + var versionToUse = normalizeElectron(version) + var chrome = e2c[versionToUse] + if (!chrome) { + throw new BrowserslistError( + 'Unknown version ' + version + ' of electron') + } + return ['chrome ' + chrome] + } + }, + { + regexp: /^node\s+(\d+(\.\d+)?(\.\d+)?)$/i, + select: function (context, version) { + var nodeReleases = jsReleases.filter(function (i) { + return i.name === 'nodejs' + }) + var matched = nodeReleases.filter(function (i) { + return isVersionsMatch(i.version, version) + }) + if (matched.length === 0) { + if (context.ignoreUnknownVersions) { + return [] + } else { + throw new BrowserslistError( + 'Unknown version ' + version + ' of Node.js') + } + } + return ['node ' + matched[matched.length - 1].version] + } + }, + { + regexp: /^current\s+node$/i, + select: function (context) { + return [env.currentNode(resolve, context)] + } + }, + { + regexp: /^maintained\s+node\s+versions$/i, + select: function (context) { + var now = Date.now() + var queries = Object.keys(jsEOL).filter(function (key) { + return now < Date.parse(jsEOL[key].end) && + now > Date.parse(jsEOL[key].start) && + isEolReleased(key) + }).map(function (key) { + return 'node ' + key.slice(1) + }) + return resolve(queries, context) + } + }, + { + regexp: /^phantomjs\s+1.9$/i, + select: function () { + return ['safari 5'] + } + }, + { + regexp: /^phantomjs\s+2.1$/i, + select: function () { + return ['safari 6'] + } + }, + { + regexp: /^(\w+)\s+(tp|[\d.]+)$/i, + select: function (context, name, version) { + if (/^tp$/i.test(version)) version = 'TP' + var data = checkName(name) + var alias = normalizeVersion(data, version, context) + if (alias) { + version = alias + } else { + if (version.indexOf('.') === -1) { + alias = version + '.0' + } else { + alias = version.replace(/\.0$/, '') + } + alias = normalizeVersion(data, alias, context) + if (alias) { + version = alias + } else if (context.ignoreUnknownVersions) { + return [] + } else { + throw new BrowserslistError( + 'Unknown version ' + version + ' of ' + name) + } + } + return [data.name + ' ' + version] + } + }, + { + regexp: /^extends (.+)$/i, + select: function (context, name) { + return resolve(env.loadQueries(context, name), context) + } + }, + { + regexp: /^defaults$/i, + select: function () { + return browserslist(browserslist.defaults) + } + }, + { + regexp: /^dead$/i, + select: function (context) { + var dead = [ + 'ie <= 10', 'ie_mob <= 10', + 'bb <= 10', + 'op_mob <= 12.1', + 'samsung 4' + ] + return resolve(dead, context) + } + }, + { + regexp: /^(\w+)$/i, + select: function (context, name) { + if (byName(name)) { + throw new BrowserslistError( + 'Specify versions in Browserslist query for browser ' + name) + } else { + throw unknownQuery(name) + } + } + } +]; + +// Get and convert Can I Use data + +(function () { + for (var name in agents) { + var browser = agents[name] + browserslist.data[name] = { + name: name, + versions: normalize(agents[name].versions), + released: normalize(agents[name].versions.slice(0, -3)), + releaseDate: agents[name].release_date + } + fillUsage(browserslist.usage.global, name, browser.usage_global) + + browserslist.versionAliases[name] = { } + for (var i = 0; i < browser.versions.length; i++) { + var full = browser.versions[i] + if (!full) continue + + if (full.indexOf('-') !== -1) { + var interval = full.split('-') + for (var j = 0; j < interval.length; j++) { + browserslist.versionAliases[name][interval[j]] = full + } + } + } + } +}()) + +module.exports = browserslist diff --git a/node_modules/browserslist/node.js b/node_modules/browserslist/node.js new file mode 100644 index 0000000..d080075 --- /dev/null +++ b/node_modules/browserslist/node.js @@ -0,0 +1,318 @@ +var region = require('caniuse-lite/dist/unpacker/region').default +var path = require('path') +var fs = require('fs') + +var BrowserslistError = require('./error') + +var IS_SECTION = /^\s*\[(.+)\]\s*$/ +var CONFIG_PATTERN = /^browserslist-config-/ +var SCOPED_CONFIG__PATTERN = /@[^/]+\/browserslist-config(-|$|\/)/ +var TIME_TO_UPDATE_CANIUSE = 6 * 30 * 24 * 60 * 60 * 1000 +var FORMAT = 'Browserslist config should be a string or an array ' + + 'of strings with browser queries' + +var dataTimeChecked = false +var filenessCache = { } +var configCache = { } +function checkExtend (name) { + var use = ' Use `dangerousExtend` option to disable.' + if (!CONFIG_PATTERN.test(name) && !SCOPED_CONFIG__PATTERN.test(name)) { + throw new BrowserslistError( + 'Browserslist config needs `browserslist-config-` prefix. ' + use) + } + if (name.replace(/^@[^/]+\//, '').indexOf('.') !== -1) { + throw new BrowserslistError( + '`.` not allowed in Browserslist config name. ' + use) + } + if (name.indexOf('node_modules') !== -1) { + throw new BrowserslistError( + '`node_modules` not allowed in Browserslist config.' + use) + } +} + +function isFile (file) { + if (file in filenessCache) { + return filenessCache[file] + } + var result = fs.existsSync(file) && fs.statSync(file).isFile() + if (!process.env.BROWSERSLIST_DISABLE_CACHE) { + filenessCache[file] = result + } + return result +} + +function eachParent (file, callback) { + var loc = path.resolve(file) + do { + var result = callback(loc) + if (typeof result !== 'undefined') return result + } while (loc !== (loc = path.dirname(loc))) + return undefined +} + +function check (section) { + if (Array.isArray(section)) { + for (var i = 0; i < section.length; i++) { + if (typeof section[i] !== 'string') { + throw new BrowserslistError(FORMAT) + } + } + } else if (typeof section !== 'string') { + throw new BrowserslistError(FORMAT) + } +} + +function pickEnv (config, opts) { + if (typeof config !== 'object') return config + + var name + if (typeof opts.env === 'string') { + name = opts.env + } else if (process.env.BROWSERSLIST_ENV) { + name = process.env.BROWSERSLIST_ENV + } else if (process.env.NODE_ENV) { + name = process.env.NODE_ENV + } else { + name = 'production' + } + + return config[name] || config.defaults +} + +function parsePackage (file) { + var config = JSON.parse(fs.readFileSync(file)) + if (config.browserlist && !config.browserslist) { + throw new BrowserslistError( + '`browserlist` key instead of `browserslist` in ' + file) + } + var list = config.browserslist + if (Array.isArray(list) || typeof list === 'string') { + list = { defaults: list } + } + for (var i in list) { + check(list[i]) + } + + return list +} + +function latestReleaseTime (agents) { + var latest = 0 + for (var name in agents) { + var dates = agents[name].releaseDate || { } + for (var key in dates) { + if (latest < dates[key]) { + latest = dates[key] + } + } + } + return latest * 1000 +} + +module.exports = { + loadQueries: function loadQueries (context, name) { + if (!context.dangerousExtend) checkExtend(name) + // eslint-disable-next-line security/detect-non-literal-require + var queries = require(require.resolve(name, { paths: ['.'] })) + if (!Array.isArray(queries)) { + throw new BrowserslistError( + '`' + name + '` config exports not an array of queries') + } + return queries + }, + + getStat: function getStat (opts, data) { + var stats + if (opts.stats) { + stats = opts.stats + } else if (process.env.BROWSERSLIST_STATS) { + stats = process.env.BROWSERSLIST_STATS + } else if (opts.path && path.resolve && fs.existsSync) { + stats = eachParent(opts.path, function (dir) { + var file = path.join(dir, 'browserslist-stats.json') + return isFile(file) ? file : undefined + }) + } + + if (typeof stats === 'string') { + try { + stats = JSON.parse(fs.readFileSync(stats)) + } catch (e) { + throw new BrowserslistError('Can\'t read ' + stats) + } + } + + if (stats && 'dataByBrowser' in stats) { + stats = stats.dataByBrowser + } + + if (typeof stats !== 'object') return undefined + + var normalized = { } + for (var i in stats) { + var versions = Object.keys(stats[i]) + if (versions.length === 1 && data[i] && data[i].versions.length === 1) { + var normal = Object.keys(data[i].versions)[0] + normalized[i] = { } + normalized[i][normal] = stats[i][versions[0]] + } else { + normalized[i] = stats[i] + } + } + + return normalized + }, + + loadConfig: function loadConfig (opts) { + if (process.env.BROWSERSLIST) { + return process.env.BROWSERSLIST + } else if (opts.config || process.env.BROWSERSLIST_CONFIG) { + var file = opts.config || process.env.BROWSERSLIST_CONFIG + if (path.basename(file) === 'package.json') { + return pickEnv(parsePackage(file), opts) + } else { + return pickEnv(module.exports.readConfig(file), opts) + } + } else if (opts.path) { + return pickEnv(module.exports.findConfig(opts.path), opts) + } else { + return undefined + } + }, + + loadCountry: function loadCountry (usage, country) { + var code = country.replace(/[^\w-]/g, '') + if (!usage[code]) { + // eslint-disable-next-line security/detect-non-literal-require + var compressed = require('caniuse-lite/data/regions/' + code + '.js') + var data = region(compressed) + usage[country] = { } + for (var i in data) { + for (var j in data[i]) { + usage[country][i + ' ' + j] = data[i][j] + } + } + } + }, + + parseConfig: function parseConfig (string) { + var result = { defaults: [] } + var sections = ['defaults'] + + string.toString() + .replace(/#[^\n]*/g, '') + .split(/\n|,/) + .map(function (line) { + return line.trim() + }) + .filter(function (line) { + return line !== '' + }) + .forEach(function (line) { + if (IS_SECTION.test(line)) { + sections = line.match(IS_SECTION)[1].trim().split(' ') + sections.forEach(function (section) { + if (result[section]) { + throw new BrowserslistError( + 'Duplicate section ' + section + ' in Browserslist config') + } + result[section] = [] + }) + } else { + sections.forEach(function (section) { + result[section].push(line) + }) + } + }) + + return result + }, + + readConfig: function readConfig (file) { + if (!isFile(file)) { + throw new BrowserslistError('Can\'t read ' + file + ' config') + } + return module.exports.parseConfig(fs.readFileSync(file)) + }, + + findConfig: function findConfig (from) { + from = path.resolve(from) + + var cacheKey = isFile(from) ? path.dirname(from) : from + if (cacheKey in configCache) { + return configCache[cacheKey] + } + + var resolved = eachParent(from, function (dir) { + var config = path.join(dir, 'browserslist') + var pkg = path.join(dir, 'package.json') + var rc = path.join(dir, '.browserslistrc') + + var pkgBrowserslist + if (isFile(pkg)) { + try { + pkgBrowserslist = parsePackage(pkg) + } catch (e) { + if (e.name === 'BrowserslistError') throw e + console.warn( + '[Browserslist] Could not parse ' + pkg + '. Ignoring it.') + } + } + + if (isFile(config) && pkgBrowserslist) { + throw new BrowserslistError( + dir + ' contains both browserslist and package.json with browsers') + } else if (isFile(rc) && pkgBrowserslist) { + throw new BrowserslistError( + dir + ' contains both .browserslistrc and package.json with browsers') + } else if (isFile(config) && isFile(rc)) { + throw new BrowserslistError( + dir + ' contains both .browserslistrc and browserslist') + } else if (isFile(config)) { + return module.exports.readConfig(config) + } else if (isFile(rc)) { + return module.exports.readConfig(rc) + } else { + return pkgBrowserslist + } + }) + if (!process.env.BROWSERSLIST_DISABLE_CACHE) { + configCache[cacheKey] = resolved + } + return resolved + }, + + clearCaches: function clearCaches () { + dataTimeChecked = false + filenessCache = { } + configCache = { } + }, + + oldDataWarning: function oldDataWarning (agentsObj) { + if (dataTimeChecked) return + dataTimeChecked = true + if (process.env.BROWSERSLIST_IGNORE_OLD_DATA) return + + var latest = latestReleaseTime(agentsObj) + var halfYearAgo = Date.now() - TIME_TO_UPDATE_CANIUSE + + if (latest !== 0 && latest < halfYearAgo) { + var command = 'npm update' + eachParent(__filename, function (dir) { + var pckg = path.join(dir, 'package.json') + var yarnLock = path.join(dir, 'yarn.lock') + if (isFile(pckg) && isFile(yarnLock)) { + command = 'yarn upgrade' + } + }) + console.warn( + 'Browserslist: caniuse-lite is outdated. ' + + 'Please run next command `' + command + '`' + ) + } + }, + + currentNode: function currentNode () { + return 'node ' + process.versions.node + } +} diff --git a/node_modules/browserslist/package.json b/node_modules/browserslist/package.json new file mode 100644 index 0000000..c05e040 --- /dev/null +++ b/node_modules/browserslist/package.json @@ -0,0 +1,66 @@ +{ + "_from": "browserslist@^4.7.0", + "_id": "browserslist@4.7.0", + "_inBundle": false, + "_integrity": "sha512-9rGNDtnj+HaahxiVV38Gn8n8Lr8REKsel68v1sPFfIGEK6uSXTY3h9acgiT1dZVtOOUtifo/Dn8daDQ5dUgVsA==", + "_location": "/browserslist", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "browserslist@^4.7.0", + "name": "browserslist", + "escapedName": "browserslist", + "rawSpec": "^4.7.0", + "saveSpec": null, + "fetchSpec": "^4.7.0" + }, + "_requiredBy": [ + "/autoprefixer" + ], + "_resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.7.0.tgz", + "_shasum": "9ee89225ffc07db03409f2fee524dc8227458a17", + "_spec": "browserslist@^4.7.0", + "_where": "/home/dstaesse/git/website/node_modules/autoprefixer", + "author": { + "name": "Andrey Sitnik", + "email": "andrey@sitnik.ru" + }, + "bin": { + "browserslist": "./cli.js" + }, + "browser": { + "./node.js": "./browser.js", + "path": false + }, + "bugs": { + "url": "https://github.com/browserslist/browserslist/issues" + }, + "bundleDependencies": false, + "dependencies": { + "caniuse-lite": "^1.0.30000989", + "electron-to-chromium": "^1.3.247", + "node-releases": "^1.1.29" + }, + "deprecated": false, + "description": "Share target browsers between different front-end tools, like Autoprefixer, Stylelint and babel-env-preset", + "eslintIgnore": [ + "test/fixtures" + ], + "homepage": "https://github.com/browserslist/browserslist#readme", + "keywords": [ + "caniuse", + "browsers", + "target" + ], + "license": "MIT", + "name": "browserslist", + "repository": { + "type": "git", + "url": "git+https://github.com/browserslist/browserslist.git" + }, + "sharec": { + "version": "0.4.2" + }, + "version": "4.7.0" +} -- cgit v1.2.3