All Downloads are FREE. Search and download functionalities are using the official Maven repository.

package.lib.config.browserslistTargetHandler.js Maven / Gradle / Ivy

Go to download

Packs ECMAScript/CommonJs/AMD modules for the browser. Allows you to split your codebase into multiple bundles, which can be loaded on demand. Supports loaders to preprocess files, i.e. json, jsx, es7, css, less, ... and your custom stuff.

The newest version!
/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Sergey Melyukov @smelukov
*/

"use strict";

const browserslist = require("browserslist");
const path = require("path");

/** @typedef {import("./target").ApiTargetProperties} ApiTargetProperties */
/** @typedef {import("./target").EcmaTargetProperties} EcmaTargetProperties */
/** @typedef {import("./target").PlatformTargetProperties} PlatformTargetProperties */

// [[C:]/path/to/config][:env]
const inputRx = /^(?:((?:[A-Z]:)?[/\\].*?))?(?::(.+?))?$/i;

/**
 * @typedef {object} BrowserslistHandlerConfig
 * @property {string=} configPath
 * @property {string=} env
 * @property {string=} query
 */

/**
 * @param {string | null | undefined} input input string
 * @param {string} context the context directory
 * @returns {BrowserslistHandlerConfig} config
 */
const parse = (input, context) => {
	if (!input) {
		return {};
	}

	if (path.isAbsolute(input)) {
		const [, configPath, env] = inputRx.exec(input) || [];
		return { configPath, env };
	}

	const config = browserslist.findConfig(context);

	if (config && Object.keys(config).includes(input)) {
		return { env: input };
	}

	return { query: input };
};

/**
 * @param {string | null | undefined} input input string
 * @param {string} context the context directory
 * @returns {string[] | undefined} selected browsers
 */
const load = (input, context) => {
	const { configPath, env, query } = parse(input, context);

	// 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
			? browserslist.loadConfig({
					config: configPath,
					env
				})
			: browserslist.loadConfig({ path: context, env });

	if (!config) return;
	return browserslist(config);
};

/**
 * @param {string[]} browsers supported browsers list
 * @returns {EcmaTargetProperties & PlatformTargetProperties & ApiTargetProperties} target properties
 */
const resolve = browsers => {
	/**
	 * Checks all against a version number
	 * @param {Record} versions first supported version
	 * @returns {boolean} true if supports
	 */
	const rawChecker = versions => {
		return browsers.every(v => {
			const [name, parsedVersion] = v.split(" ");
			if (!name) return false;
			const requiredVersion = versions[name];
			if (!requiredVersion) return false;
			const [parsedMajor, parserMinor] =
				// safari TP supports all features for normal safari
				parsedVersion === "TP"
					? [Infinity, Infinity]
					: parsedVersion.includes("-")
						? parsedVersion.split("-")[0].split(".")
						: parsedVersion.split(".");
			if (typeof requiredVersion === "number") {
				return +parsedMajor >= requiredVersion;
			}
			return requiredVersion[0] === +parsedMajor
				? +parserMinor >= requiredVersion[1]
				: +parsedMajor > requiredVersion[0];
		});
	};
	const anyNode = browsers.some(b => /^node /.test(b));
	const anyBrowser = browsers.some(b => /^(?!node)/.test(b));
	const browserProperty = !anyBrowser ? false : anyNode ? null : true;
	const nodeProperty = !anyNode ? false : anyBrowser ? null : true;
	// Internet Explorer Mobile, Blackberry browser and Opera Mini are very old browsers, they do not support new features
	const es6DynamicImport = rawChecker({
		chrome: 63,
		and_chr: 63,
		edge: 79,
		firefox: 67,
		and_ff: 67,
		// ie: Not supported
		opera: 50,
		op_mob: 46,
		safari: [11, 1],
		ios_saf: [11, 3],
		samsung: [8, 2],
		android: 63,
		and_qq: [10, 4],
		baidu: [13, 18],
		and_uc: [15, 5],
		kaios: [3, 0],
		node: [12, 17]
	});

	return {
		const: rawChecker({
			chrome: 49,
			and_chr: 49,
			edge: 12,
			// Prior to Firefox 13, const is implemented, but re-assignment is not failing.
			// Prior to Firefox 46, a TypeError was thrown on redeclaration instead of a SyntaxError.
			firefox: 36,
			and_ff: 36,
			// Not supported in for-in and for-of loops
			// ie: Not supported
			opera: 36,
			op_mob: 36,
			safari: [10, 0],
			ios_saf: [10, 0],
			// Before 5.0 supported correctly in strict mode, otherwise supported without block scope
			samsung: [5, 0],
			android: 37,
			and_qq: [10, 4],
			// Supported correctly in strict mode, otherwise supported without block scope
			baidu: [13, 18],
			and_uc: [12, 12],
			kaios: [2, 5],
			node: [6, 0]
		}),
		arrowFunction: rawChecker({
			chrome: 45,
			and_chr: 45,
			edge: 12,
			// The initial implementation of arrow functions in Firefox made them automatically strict. This has been changed as of Firefox 24. The use of 'use strict'; is now required.
			// Prior to Firefox 39, a line terminator (\\n) was incorrectly allowed after arrow function arguments. This has been fixed to conform to the ES2015 specification and code like () \\n => {} will now throw a SyntaxError in this and later versions.
			firefox: 39,
			and_ff: 39,
			// ie: Not supported,
			opera: 32,
			op_mob: 32,
			safari: 10,
			ios_saf: 10,
			samsung: [5, 0],
			android: 45,
			and_qq: [10, 4],
			baidu: [7, 12],
			and_uc: [12, 12],
			kaios: [2, 5],
			node: [6, 0]
		}),
		forOf: rawChecker({
			chrome: 38,
			and_chr: 38,
			edge: 12,
			// Prior to Firefox 51, using the for...of loop construct with the const keyword threw a SyntaxError ("missing = in const declaration").
			firefox: 51,
			and_ff: 51,
			// ie: Not supported,
			opera: 25,
			op_mob: 25,
			safari: 7,
			ios_saf: 7,
			samsung: [3, 0],
			android: 38,
			// and_qq: Unknown support
			// baidu: Unknown support
			// and_uc: Unknown support
			kaios: [3, 0],
			node: [0, 12]
		}),
		destructuring: rawChecker({
			chrome: 49,
			and_chr: 49,
			edge: 14,
			firefox: 41,
			and_ff: 41,
			// ie: Not supported,
			opera: 36,
			op_mob: 36,
			safari: 8,
			ios_saf: 8,
			samsung: [5, 0],
			android: 49,
			// and_qq: Unknown support
			// baidu: Unknown support
			// and_uc: Unknown support
			kaios: [2, 5],
			node: [6, 0]
		}),
		bigIntLiteral: rawChecker({
			chrome: 67,
			and_chr: 67,
			edge: 79,
			firefox: 68,
			and_ff: 68,
			// ie: Not supported,
			opera: 54,
			op_mob: 48,
			safari: 14,
			ios_saf: 14,
			samsung: [9, 2],
			android: 67,
			and_qq: [13, 1],
			baidu: [13, 18],
			and_uc: [15, 5],
			kaios: [3, 0],
			node: [10, 4]
		}),
		// Support syntax `import` and `export` and no limitations and bugs on Node.js
		// Not include `export * as namespace`
		module: rawChecker({
			chrome: 61,
			and_chr: 61,
			edge: 16,
			firefox: 60,
			and_ff: 60,
			// ie: Not supported,
			opera: 48,
			op_mob: 45,
			safari: [10, 1],
			ios_saf: [10, 3],
			samsung: [8, 0],
			android: 61,
			and_qq: [10, 4],
			baidu: [13, 18],
			and_uc: [15, 5],
			kaios: [3, 0],
			node: [12, 17]
		}),
		dynamicImport: es6DynamicImport,
		dynamicImportInWorker: es6DynamicImport && !anyNode,
		// browserslist does not have info about globalThis
		// so this is based on mdn-browser-compat-data
		globalThis: rawChecker({
			chrome: 71,
			and_chr: 71,
			edge: 79,
			firefox: 65,
			and_ff: 65,
			// ie: Not supported,
			opera: 58,
			op_mob: 50,
			safari: [12, 1],
			ios_saf: [12, 2],
			samsung: [10, 1],
			android: 71,
			// and_qq: Unknown support
			// baidu: Unknown support
			// and_uc: Unknown support
			kaios: [3, 0],
			node: 12
		}),
		optionalChaining: rawChecker({
			chrome: 80,
			and_chr: 80,
			edge: 80,
			firefox: 74,
			and_ff: 79,
			// ie: Not supported,
			opera: 67,
			op_mob: 64,
			safari: [13, 1],
			ios_saf: [13, 4],
			samsung: 13,
			android: 80,
			// and_qq: Not supported
			// baidu: Not supported
			// and_uc: Not supported
			kaios: [3, 0],
			node: 14
		}),
		templateLiteral: rawChecker({
			chrome: 41,
			and_chr: 41,
			edge: 13,
			firefox: 34,
			and_ff: 34,
			// ie: Not supported,
			opera: 29,
			op_mob: 64,
			safari: [9, 1],
			ios_saf: 9,
			samsung: 4,
			android: 41,
			and_qq: [10, 4],
			baidu: [7, 12],
			and_uc: [12, 12],
			kaios: [2, 5],
			node: 4
		}),
		asyncFunction: rawChecker({
			chrome: 55,
			and_chr: 55,
			edge: 15,
			firefox: 52,
			and_ff: 52,
			// ie: Not supported,
			opera: 42,
			op_mob: 42,
			safari: 11,
			ios_saf: 11,
			samsung: [6, 2],
			android: 55,
			and_qq: [13, 1],
			baidu: [13, 18],
			and_uc: [15, 5],
			kaios: 3,
			node: [7, 6]
		}),
		browser: browserProperty,
		electron: false,
		node: nodeProperty,
		nwjs: false,
		web: browserProperty,
		webworker: false,

		document: browserProperty,
		fetchWasm: browserProperty,
		global: nodeProperty,
		importScripts: false,
		importScriptsInWorker: true,
		nodeBuiltins: nodeProperty,
		nodePrefixForCoreModules:
			nodeProperty &&
			!browsers.some(b => /^node 15/.test(b)) &&
			rawChecker({
				node: [14, 18]
			}),
		require: nodeProperty
	};
};

module.exports = {
	resolve,
	load
};




© 2015 - 2024 Weber Informatics LLC | Privacy Policy