UNPKG

parcel-bundler

Version:

Blazing fast, zero configuration web application bundler

367 lines (281 loc) 13.5 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray")); var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator")); function _createForOfIteratorHelper(o, allowArrayLike) { var it; if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = o[Symbol.iterator](); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } const semver = require('semver'); const logger = require('@parcel/logger'); const path = require('path'); const localRequire = require('../../utils/localRequire'); const installPackage = require('../../utils/installPackage'); const fs = require('@parcel/fs'); const micromatch = require('micromatch'); function getBabelConfig(_x, _x2) { return _getBabelConfig.apply(this, arguments); } function _getBabelConfig() { _getBabelConfig = (0, _asyncToGenerator2.default)(function* (asset, isSource) { let config = yield getBabelRc(asset, isSource); if (!config) { return null; } // Ignore if the config is empty. if ((!config.plugins || config.plugins.length === 0) && (!config.presets || config.presets.length === 0)) { return null; } let plugins = yield installPlugins(asset, config); let babelVersion = yield getBabelVersion(asset, plugins); return { babelVersion, config }; }); return _getBabelConfig.apply(this, arguments); } module.exports = getBabelConfig; /** * Finds a .babelrc for an asset. By default, .babelrc files inside node_modules are not used. * However, there are some exceptions: * - if `browserify.transforms` includes "babelify" in package.json (for legacy module compat) * - the `source` field in package.json is used by the resolver */ function getBabelRc(_x3, _x4) { return _getBabelRc.apply(this, arguments); } function _getBabelRc() { _getBabelRc = (0, _asyncToGenerator2.default)(function* (asset, isSource) { // Support legacy browserify packages let pkg = yield asset.getPackage(); let browserify = pkg && pkg.browserify; if (browserify && Array.isArray(browserify.transform)) { // Look for babelify in the browserify transform list let babelify = browserify.transform.find(t => (Array.isArray(t) ? t[0] : t) === 'babelify'); // If specified as an array, override the config with the one specified if (Array.isArray(babelify) && babelify[1]) { return babelify[1]; } // Otherwise, return the .babelrc if babelify was found return babelify ? findBabelRc(asset) : null; } // If this asset is not in node_modules, always use the .babelrc if (isSource) { return findBabelRc(asset); } // Otherwise, don't load .babelrc for node_modules. // See https://github.com/parcel-bundler/parcel/issues/13. return null; }); return _getBabelRc.apply(this, arguments); } function findBabelRc(_x5) { return _findBabelRc.apply(this, arguments); } function _findBabelRc() { _findBabelRc = (0, _asyncToGenerator2.default)(function* (asset) { // TODO: use the babel API to do this config resolution and support all of its features. // This is not currently possible because babel tries to actually load plugins and presets // while resolving the config, but those plugins might not be installed yet. let config = yield asset.getConfig(['.babelrc', '.babelrc.js'], { packageKey: 'babel' }); if (!config) { return null; } if (typeof config === 'function') { // We cannot support function configs since there is no exposed method in babel // to create the API that is passed to them... throw new Error('Parcel does not support function configs in .babelrc.js yet.'); } for (var _i = 0, _arr = ['extends', 'overrides', 'test', 'include', 'exclude']; _i < _arr.length; _i++) { let key = _arr[_i]; if (config[key]) { throw new Error(`Parcel does not support babel 7 advanced configuration option "${key}" yet.`); } } // Support ignore/only config options. if (shouldIgnore(asset, config)) { return null; } // Support .babelignore let ignoreConfig = yield getIgnoreConfig(asset); if (ignoreConfig && shouldIgnore(asset, ignoreConfig)) { return null; } return config; }); return _findBabelRc.apply(this, arguments); } function getIgnoreConfig(_x6) { return _getIgnoreConfig.apply(this, arguments); } function _getIgnoreConfig() { _getIgnoreConfig = (0, _asyncToGenerator2.default)(function* (asset) { let ignoreFile = yield asset.getConfig(['.babelignore'], { load: false }); if (!ignoreFile) { return null; } let data = yield fs.readFile(ignoreFile, 'utf8'); let patterns = data.split('\n').map(line => line.replace(/#.*$/, '').trim()).filter(Boolean); return { ignore: patterns }; }); return _getIgnoreConfig.apply(this, arguments); } function shouldIgnore(asset, config) { if (config.ignore && matchesPatterns(config.ignore, asset.name)) { return true; } if (config.only && !matchesPatterns(config.only, asset.name)) { return true; } return false; } function matchesPatterns(patterns, path) { return patterns.some(pattern => { if (typeof pattern === 'function') { return !!pattern(path); } if (typeof pattern === 'string') { return micromatch.isMatch(path, '**/' + pattern + '/**'); } return pattern.test(path); }); } function getBabelVersion(_x7, _x8) { return _getBabelVersion.apply(this, arguments); } function _getBabelVersion() { _getBabelVersion = (0, _asyncToGenerator2.default)(function* (asset, plugins) { // Check the package.json to determine the babel version that is installed let pkg = yield asset.getPackage(); let babelLegacy = getDependency(pkg, 'babel-core'); let babelModern = getDependency(pkg, '@babel/core'); if (babelModern) { return getMaxMajor(babelModern); } if (babelLegacy) { return 6; } // No version was installed. This is either an old app where we didn't require a version to be installed, // or a new app that just added a .babelrc without manually installing a version of babel core. // We will attempt to infer a verison of babel and install it based on the dependencies of the plugins // in the config. This should only happen once since we save babel core into package.json for subsequent runs. let inferred = yield inferBabelVersion(asset, plugins); let name = inferred === 6 ? 'babel-core' : `@babel/core`; yield installPackage(name, asset.name); return inferred; }); return _getBabelVersion.apply(this, arguments); } function getDependency(pkg, dep) { return pkg.dependencies && pkg.dependencies[dep] || pkg.peerDependencies && pkg.peerDependencies[dep] || pkg.devDependencies && pkg.devDependencies[dep]; } // Core babel packages we use to infer the major version of babel to use. const CORE_DEPS = new Set(['@babel/core', '@babel/runtime', '@babel/template', '@babel/traverse', '@babel/types', '@babel/parser', '@babel/cli', '@babel/register', '@babel/generator', 'babel-core', 'babel-runtime', 'babel-template', 'babel-traverse', 'babel-types', 'babylon', 'babel-cli', 'babel-register', 'babel-generator']); function inferBabelVersion(_x9, _x10) { return _inferBabelVersion.apply(this, arguments); } function _inferBabelVersion() { _inferBabelVersion = (0, _asyncToGenerator2.default)(function* (asset, plugins) { // Attempt to determine version based on dependencies of plugins let version; var _iterator = _createForOfIteratorHelper(plugins), _step; try { for (_iterator.s(); !(_step = _iterator.n()).done;) { let pkg = _step.value; if (!pkg) { continue; } var _iterator2 = _createForOfIteratorHelper(CORE_DEPS), _step2; try { for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) { let name = _step2.value; let dep = getDependency(pkg, name); if (dep) { // Parse version range (ignore prerelease), and ensure it overlaps with the existing version (if any) let range = new semver.Range(dep.replace(/-.*(\s|\|\||$)?/, '')); if (version && !version.intersects(range)) { throw new Error('Conflicting babel versions found in .babelrc. Make sure all of your plugins and presets depend on the same major version of babel.'); } version = range; break; } } } catch (err) { _iterator2.e(err); } finally { _iterator2.f(); } } // Find the maximum major version allowed in the range and use that. // e.g. if ^6 || ^7 were specified, use 7. } catch (err) { _iterator.e(err); } finally { _iterator.f(); } version = getMaxMajor(version); if (!version) { logger.warn(`Could not infer babel version. Defaulting to babel 7. Please add either babel-core or @babel/core as a dependency.`); version = 7; } return version; }); return _inferBabelVersion.apply(this, arguments); } function getPluginName(p) { return Array.isArray(p) ? p[0] : p; } function getMaxMajor(version) { try { let range = new semver.Range(version); let sorted = range.set.sort((a, b) => a[0].semver.compare(b[0].semver)); return semver.major(sorted.pop()[0].semver.version); } catch (err) { return null; } } function installPlugins(_x11, _x12) { return _installPlugins.apply(this, arguments); } function _installPlugins() { _installPlugins = (0, _asyncToGenerator2.default)(function* (asset, babelrc) { let presets = (babelrc.presets || []).map(p => resolveModule('preset', getPluginName(p), asset.name)); let plugins = (babelrc.plugins || []).map(p => resolveModule('plugin', getPluginName(p), asset.name)); return Promise.all([...presets, ...plugins]); }); return _installPlugins.apply(this, arguments); } function resolveModule(_x13, _x14, _x15) { return _resolveModule.apply(this, arguments); } // Copied from https://github.com/babel/babel/blob/3a399d1eb907df520f2b85bf9ddbc6533e256f6d/packages/babel-core/src/config/files/plugins.js#L61 function _resolveModule() { _resolveModule = (0, _asyncToGenerator2.default)(function* (type, name, path) { try { name = standardizeName(type, name); let _yield$localRequire$r = yield localRequire.resolve(name, path), _yield$localRequire$r2 = (0, _slicedToArray2.default)(_yield$localRequire$r, 2), pkg = _yield$localRequire$r2[1]; return pkg; } catch (err) { return null; } }); return _resolveModule.apply(this, arguments); } const EXACT_RE = /^module:/; const BABEL_PLUGIN_PREFIX_RE = /^(?!@|module:|[^/]+\/|babel-plugin-)/; const BABEL_PRESET_PREFIX_RE = /^(?!@|module:|[^/]+\/|babel-preset-)/; const BABEL_PLUGIN_ORG_RE = /^(@babel\/)(?!plugin-|[^/]+\/)/; const BABEL_PRESET_ORG_RE = /^(@babel\/)(?!preset-|[^/]+\/)/; const OTHER_PLUGIN_ORG_RE = /^(@(?!babel\/)[^/]+\/)(?![^/]*babel-plugin(?:-|\/|$)|[^/]+\/)/; const OTHER_PRESET_ORG_RE = /^(@(?!babel\/)[^/]+\/)(?![^/]*babel-preset(?:-|\/|$)|[^/]+\/)/; const OTHER_ORG_DEFAULT_RE = /^(@(?!babel$)[^/]+)$/; function standardizeName(type, name) { // Let absolute and relative paths through. if (path.isAbsolute(name)) return name; const isPreset = type === 'preset'; return name // foo -> babel-preset-foo .replace(isPreset ? BABEL_PRESET_PREFIX_RE : BABEL_PLUGIN_PREFIX_RE, `babel-${type}-`) // @babel/es2015 -> @babel/preset-es2015 .replace(isPreset ? BABEL_PRESET_ORG_RE : BABEL_PLUGIN_ORG_RE, `$1${type}-`) // @foo/mypreset -> @foo/babel-preset-mypreset .replace(isPreset ? OTHER_PRESET_ORG_RE : OTHER_PLUGIN_ORG_RE, `$1babel-${type}-`) // @foo -> @foo/babel-preset .replace(OTHER_ORG_DEFAULT_RE, `$1/babel-${type}`) // module:mypreset -> mypreset .replace(EXACT_RE, ''); }