UNPKG

4.23 kBJavaScriptView Raw
1var _ = require("lodash");
2var path = require("path");
3var babel = require("babel-standalone");
4
5/**
6 * A Babel preset as defined in `babelOptions.presets`
7 * @typedef {string|Function|Object|<string, Object>[]|<Function, Object>[], <Object, Object>} BabelPreset
8 */
9
10/**
11 * The options needed to load presets not built in babel-standalone
12 * @typedef {Object} LoadCustomPluginsOptions
13 * @property {string} baseURL The loader baseURL value
14 * @property {string} loaderEnv The loader env value
15 * @property {Object} babelOptions The babel configuration options
16 */
17
18/**
19 * Returns a list of babel presets to be used by transpile
20 * @param {LoadCustomPresetsOptions} opts The options object
21 * @return {BabelPreset[]} The list of presets to be used by transpile
22 */
23module.exports = function(opts) {
24 var processed = [];
25 var babelOptions = opts.babelOptions || {};
26 var babelEnvConfig = babelOptions.env || {};
27
28 var babelEnv = process.env.BABEL_ENV ||
29 process.env.NODE_ENV ||
30 opts.loaderEnv;
31
32 // process presets in babelOptions.presets
33 processed = processed.concat(processPresets(opts.baseURL, babelOptions.presets));
34
35 // process environment dependant presets
36 _.keys(babelEnvConfig).forEach(function(envName) {
37 // do not process presets if the current environment does not match
38 // the environment in which the presets are set to be used
39 if (envName === babelEnv) {
40 var presets = babelEnvConfig[envName].presets || [];
41 processed = processed.concat(processPresets(opts.baseURL, presets));
42 }
43 });
44
45 return processed;
46};
47
48/**
49 * Collect built in preset names and non builtin presets functions/objects
50 * @param {string} baseURL The loader baseURL value
51 * @param {BabelPreset[]} presets An array of babel presets
52 * @return {BabelPreset[]} An array of babel presets with non-builtins replaced
53 * by their respective functions/objects
54 */
55function processPresets(baseURL, presets) {
56 var normalized = [];
57
58 // path.resolve does not work correctly if baseURL starts with "file:"
59 baseURL = baseURL.replace("file:", "");
60 presets = presets || [];
61
62 presets.forEach(function(preset) {
63 var name = getPresetName(preset);
64
65 if (!includesPresetName(preset) || isBuiltinPreset(name)) {
66 normalized.push(preset);
67 }
68 else if (!isBuiltinPreset(name)) {
69 var npmPresetNameOrPath = getNpmPresetNameOrPath(baseURL, name);
70
71 // load the preset!
72 var presetDefinition = require(npmPresetNameOrPath);
73
74 if (_.isString(preset)) {
75 normalized.push(presetDefinition);
76 }
77 else if (_.isArray(preset)) {
78 // [ presetDefinition, presetOptions ]
79 normalized.push([presetDefinition, preset[1]]);
80 }
81 }
82 });
83
84 return normalized;
85}
86
87/**
88 * Gets the babel preset name
89 * @param {BabelPreset} preset A babel preset
90 * @return {?string} The preset name
91 */
92function getPresetName(preset) {
93 if (includesPresetName(preset)) {
94 return _.isString(preset) ? preset : _.head(preset);
95 }
96 else {
97 return null;
98 }
99}
100
101/**
102 * Whether the babel preset name was provided
103 * @param {BabelPreset} preset
104 * @return {boolean}
105 */
106function includesPresetName(preset) {
107 return _.isString(preset) ||
108 _.isArray(preset) && _.isString(_.head(preset));
109}
110
111function getNpmPresetNameOrPath(baseURL, name) {
112 var isPath = /\//;
113 var isNpmPresetName = /^(?:babel-preset-)/;
114
115 if (isPath.test(name)) {
116 return path.resolve(baseURL, name);
117 }
118 else if (!isNpmPresetName.test(name)) {
119 return "babel-preset-" + name;
120 }
121
122 return name;
123}
124
125/**
126 * Whether the preset is built in babel-standalone
127 *
128 * @param {string} name A preset path
129 * @return {boolean} `true` if preset is builtin, `false` otherwise
130 *
131 * Babel presets can be set using the following variations:
132 *
133 * 1) the npm preset name, which by convention starts with `babel-preset-`
134 * 2) A shorthand name, which is the npm name without the prefix
135 * 3) A path to where the preset is defined
136 *
137 * babel-standalone registers the builtin presets using the shorthand version.
138 */
139function isBuiltinPreset(name) {
140 var isNpmPresetName = /^(?:babel-preset-)/;
141 var availablePresets = babel.availablePresets || {};
142
143 var shorthand = isNpmPresetName.test(name) ?
144 name.replace("babel-preset-", "") :
145 name;
146
147 return !!availablePresets[shorthand];
148}