diff --git a/README.md b/README.md index 45b6e337..225f7901 100644 --- a/README.md +++ b/README.md @@ -20,19 +20,24 @@ The data for this is currently at: [/data/plugins.json](/data/plugins.json) and Currently: "chrome, edge, firefox, safari, node" -> Some node features are > `6.5` +> Some node features are > `6.5`. + +* `browsers` (array/string) - an query to select browsers (ex: last 2 versions, > 5%). + +> Note, browsers' results are overridden by explicit items from `targets`. * `loose` (boolean) - Enable "loose" transformations for any plugins in this preset that allow them (Disabled by default). * `modules` - Enable transformation of ES6 module syntax to another module type (Enabled by default to `"commonjs"`). - * Can be `false` to not transform modules, or one of `["amd", "umd", "systemjs", "commonjs"]` -* `debug` (boolean) - `console.log` out the targets and plugins being used as well as the version specified in `/data/plugins.json` + * Can be `false` to not transform modules, or one of `["amd", "umd", "systemjs", "commonjs"]`. +* `debug` (boolean) - `console.log` out the targets and plugins being used as well as the version specified in `/data/plugins.json`. ```js { "presets": [ ["env", { "targets": { - "chrome": 52 + "chrome": 52, + "browsers": "last 2 safari versions" }, "loose": true, "modules": false @@ -99,6 +104,24 @@ exports.A = A; export class A {} ``` +```js +// using browserslist +{ + "presets": [ + ["env", { + "targets": { + "chrome": 52, + "browsers": ["last 2 versions", "safari 7"] + } + }] + ] +} + +// ... + +export class A {} +``` + ### Example with `debug: true` ```js diff --git a/package.json b/package.json index 3f4a4888..de3bd292 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,8 @@ "babel-plugin-transform-es2015-typeof-symbol": "^6.6.0", "babel-plugin-transform-es2015-unicode-regex": "^6.3.13", "babel-plugin-transform-exponentiation-operator": "^6.8.0", - "babel-plugin-transform-regenerator": "^6.6.0" + "babel-plugin-transform-regenerator": "^6.6.0", + "browserslist": "^1.4.0" }, "devDependencies": { "babel-cli": "^6.11.4", diff --git a/src/index.js b/src/index.js index 3a5eaa4f..4d624645 100644 --- a/src/index.js +++ b/src/index.js @@ -5,6 +5,7 @@ // "es5-property-mutators", import pluginList from "../data/plugins.json"; +import browserslist from "browserslist"; export const plugins = [ "es3-member-expression-literals", @@ -39,6 +40,10 @@ export const MODULE_TRANSFORMATIONS = { * @return {Boolean} Whether or not the transformation is required */ export const isPluginRequired = (supportedEnvironments, plugin) => { + if (supportedEnvironments.browsers) { + supportedEnvironments = getTargets(supportedEnvironments); + } + const targetEnvironments = Object.keys(supportedEnvironments); if (targetEnvironments.length === 0) { return true; } @@ -61,8 +66,34 @@ export const isPluginRequired = (supportedEnvironments, plugin) => { return isRequiredForEnvironments.length > 0 ? true : false; }; +const isBrowsersQueryValid = browsers => { + return typeof browsers === "string" || Array.isArray(browsers); +}; + +const getLowestVersions = (browsers) => { + return browsers.reduce((all, browser) => { + const [browserName, browserVersion] = browser.split(" "); + all[browserName] = parseInt(browserVersion); + return all; + }, {}); +}; + +const mergeBrowsers = (fromQuery, fromTarget) => { + return Object.keys(fromTarget).reduce((queryObj, targKey) => { + if (targKey !== "browsers") { + queryObj[targKey] = fromTarget[targKey]; + } + return queryObj; + }, fromQuery); +}; + const getTargets = targetOpts => { - return targetOpts || {}; + const browserOpts = targetOpts.browsers; + if (isBrowsersQueryValid(browserOpts)) { + const queryBrowsers = getLowestVersions(browserslist(browserOpts)); + return mergeBrowsers(queryBrowsers, targetOpts); + } + return targetOpts; }; // TODO: Allow specifying plugins as either shortened or full name diff --git a/test/index.js b/test/index.js index 0a4c038c..a29c2187 100644 --- a/test/index.js +++ b/test/index.js @@ -65,6 +65,38 @@ describe("babel-preset-env", () => { assert(babelPresetEnv.isPluginRequired(targets, plugin) === true); }); + it("returns false if plugin feature is implemented by lower than target defined in browsers query", () => { + const plugin = { + chrome: 49, + }; + const targets = { + "browsers": "chrome > 50" + }; + assert(babelPresetEnv.isPluginRequired(targets, plugin) === false); + }); + + it("returns true if plugin feature is implemented is greater than target defined in browsers query", () => { + const plugin = { + chrome: 52, + }; + const targets = { + "browsers": "chrome > 50" + }; + assert(babelPresetEnv.isPluginRequired(targets, plugin) === true); + }); + + it("returns true if target's root items overrides versions defined in browsers query", () => { + const plugin = { + chrome: 45, + }; + const targets = { + browsers: "last 2 Chrome versions", + chrome: 44 + }; + + assert(babelPresetEnv.isPluginRequired(targets, plugin) === true); + }); + it("doesn't throw when specifiying a decimal for node", () => { let targets; const plugin = {