2020-09-24 19:33:09 +08:00
|
|
|
/*
|
|
|
|
MIT License http://www.opensource.org/licenses/mit-license.php
|
|
|
|
Author Sergey Melyukov @smelukov
|
|
|
|
*/
|
|
|
|
|
2020-09-24 19:42:27 +08:00
|
|
|
"use strict";
|
2020-09-24 19:33:09 +08:00
|
|
|
|
|
|
|
const browserslist = require("browserslist");
|
|
|
|
|
2020-09-24 20:08:09 +08:00
|
|
|
// ?query|[///path/to/config][:env]
|
|
|
|
const inputRx = /^(?:\?(.+?)|(?:\/\/(.+?))?(?::(.+?))?)$/;
|
2020-09-24 19:33:09 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @typedef {Object} BrowserslistHandlerConfig
|
|
|
|
* @property {string} [configPath]
|
|
|
|
* @property {string} [env]
|
|
|
|
* @property {string} [query]
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param {BrowserslistHandlerConfig|null} handlerConfig config
|
|
|
|
* @returns {import("./target").EcmaTargetProperties} es features
|
|
|
|
*/
|
|
|
|
const resolve = handlerConfig => {
|
2020-09-24 20:08:09 +08:00
|
|
|
const { configPath, env, query } = handlerConfig || {};
|
2020-09-24 19:33:09 +08:00
|
|
|
|
|
|
|
// if a query is specified, then use it, else
|
|
|
|
// if a path to a config is specified then load it, else
|
|
|
|
// find a nearest config
|
|
|
|
const config = query
|
|
|
|
? query
|
|
|
|
: configPath
|
2020-09-24 20:08:09 +08:00
|
|
|
? browserslist.loadConfig({
|
2020-09-24 19:33:09 +08:00
|
|
|
config: configPath,
|
|
|
|
env
|
|
|
|
})
|
2020-09-24 20:08:09 +08:00
|
|
|
: browserslist.loadConfig({ path: process.cwd(), env });
|
2020-09-24 19:33:09 +08:00
|
|
|
|
2020-09-24 20:08:09 +08:00
|
|
|
const browsers = browserslist(config);
|
|
|
|
const checker = createChecker(browsers);
|
2020-09-24 19:33:09 +08:00
|
|
|
|
|
|
|
return resolveESFeatures(checker);
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param {string} input input string
|
|
|
|
* @returns {BrowserslistHandlerConfig|null} config
|
|
|
|
*/
|
|
|
|
const parse = input => {
|
|
|
|
if (!input) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2020-09-24 20:08:09 +08:00
|
|
|
const [, query, configPath, env] = inputRx.exec(input) || [];
|
2020-09-24 19:33:09 +08:00
|
|
|
|
2020-09-24 20:08:09 +08:00
|
|
|
return { query, configPath, env };
|
2020-09-24 19:33:09 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param {function(string): boolean} checker checker function
|
|
|
|
* @returns {import("./target").EcmaTargetProperties} es features
|
|
|
|
*/
|
|
|
|
const resolveESFeatures = checker => {
|
|
|
|
return {
|
|
|
|
const: checker("es6"),
|
|
|
|
arrowFunction: checker("es6"),
|
|
|
|
forOf: checker("es6"),
|
|
|
|
destructuring: checker("es6"),
|
|
|
|
bigIntLiteral: checker("bigint"),
|
|
|
|
module: checker("es6-module"),
|
|
|
|
dynamicImport: checker("es6-module-dynamic-import"),
|
|
|
|
dynamicImportInWorker: checker("es6-module-dynamic-import"),
|
|
|
|
// browserslist does not have info about globalThis
|
|
|
|
globalThis: undefined
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Create browserslist checker
|
|
|
|
* @param {string[]} browsers supported browsers list
|
|
|
|
* @returns {function(string):boolean} checker
|
|
|
|
*/
|
2020-09-24 20:08:09 +08:00
|
|
|
const createChecker = browsers => {
|
2020-09-24 19:33:09 +08:00
|
|
|
/**
|
|
|
|
* @param {string} feature an ES feature to test
|
|
|
|
* @returns {boolean} true if supports
|
|
|
|
*/
|
|
|
|
return feature => {
|
|
|
|
const supportsFeature = browserslist(`supports ${feature}`);
|
|
|
|
return browsers.every(v => supportsFeature.includes(v));
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
module.exports = {
|
|
|
|
resolve,
|
|
|
|
parse
|
|
|
|
};
|