index.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. var path = require('path');
  2. var relative = require('require-relative');
  3. var serialize = require('./lib/serialize');
  4. var getFlattenedPlugins = require('./lib/flatten');
  5. var normalizePreset = require('./lib/normalize-preset');
  6. // strip a nested module path + filename down to just the innermost module's (file)name
  7. function getModuleName(path) {
  8. return path.replace(/(?:..[\\/])*(?:(?:.+[\\/])?node_modules[\\/]|[\\/]|\.\.[\\/])((@[^\\/]+[\\/])?[^\\/]+)([\\/].*)?$/g, '$1');
  9. }
  10. function setHiddenProp(obj, prop, value) {
  11. if (Object.defineProperty) {
  12. Object.defineProperty(obj, prop, {
  13. enumerable: false,
  14. writable: true,
  15. value: value
  16. });
  17. }
  18. else {
  19. obj[prop] = value;
  20. }
  21. }
  22. function extend(base, props) {
  23. for (var i in props) if (props.hasOwnProperty(i)) {
  24. base[i] = props[i];
  25. }
  26. return base;
  27. }
  28. function requireBabelPlugin(name, relativeTo) {
  29. if (!name.match(/^babel-plugin-/)) {
  30. name = 'babel-plugin-' + name;
  31. }
  32. var relativeName;
  33. if (relativeTo) {
  34. try {
  35. relativeName = relative.resolve(name, relativeTo);
  36. } catch (err) {}
  37. }
  38. if (!relativeName) {
  39. try {
  40. relativeName = require.resolve(name);
  41. } catch(err) {}
  42. }
  43. name = relativeName || name;
  44. return { mod:require(name), name:name };
  45. }
  46. module.exports = function(presetInput, modifications) {
  47. var options = {};
  48. if (Array.isArray(presetInput)) {
  49. options = presetInput[1];
  50. presetInput = presetInput[0];
  51. }
  52. modifications = modifications || {};
  53. var preset;
  54. if (typeof presetInput==='string') {
  55. if (!presetInput.match(/(^babel-preset-|[\\/])/)) {
  56. try {
  57. preset = relative.resolve('babel-preset-'+presetInput, __dirname);
  58. } catch(err) {
  59. console.log(err);
  60. }
  61. }
  62. if (!preset) {
  63. preset = require.resolve(presetInput);
  64. }
  65. }
  66. preset = path.resolve(preset);
  67. var presetModule = normalizePreset(require(preset), null, options);
  68. var orig = presetModule['modify-babel-preset'];
  69. if (orig) {
  70. console.log('Found nested modify-babel-preset configuration, flattening.');
  71. return modify(orig.preset, extend(extend({}, orig.modifications), modifications));
  72. }
  73. var cwd = path.dirname(preset) || process.cwd();
  74. // console.log('cwd: ', cwd);
  75. var serialized = serialize(preset, {
  76. options: options,
  77. cwd: cwd
  78. });
  79. var alias = serialized.alias;
  80. var plugins = getFlattenedPlugins(serialized);
  81. function isSameName(a, b) {
  82. if (typeof a!=='string' || typeof b!=='string') return false;
  83. return a.replace(/^babel-plugin-/i, '').toLowerCase() === b.replace(/^babel-plugin-/i, '').toLowerCase();
  84. }
  85. function indexOf(plugins, key) {
  86. for (var i=plugins.length; i--; ) {
  87. var mod = Array.isArray(plugins[i]) ? plugins[i][0] : plugins[i];
  88. var name = typeof mod==='string' && getModuleName(mod) || mod._original_name;
  89. name = alias[name] || name;
  90. if (isSameName(name, key)) {
  91. return i;
  92. }
  93. }
  94. return -1;
  95. }
  96. Object.keys(modifications).forEach(function(key) {
  97. if (key==='nameDrops' || key==='string') return;
  98. var value = modifications[key],
  99. index = indexOf(plugins, key);
  100. if (value===false) {
  101. if (index!==-1) {
  102. plugins.splice(index, 1);
  103. }
  104. else if (process.env.NODE_ENV==='development') {
  105. console.warn(key+' not found', __dirname);
  106. }
  107. }
  108. else {
  109. var imported = requireBabelPlugin(key, cwd),
  110. p = imported.mod;
  111. setHiddenProp(p, '_original_name', imported.name);
  112. if (value!==true) {
  113. p = [p].concat(value);
  114. }
  115. if (index<0) {
  116. plugins.push(p);
  117. }
  118. else {
  119. plugins[index] = p;
  120. }
  121. }
  122. });
  123. if (modifications.string!==true) {
  124. plugins = plugins.map(function(plugin) {
  125. var mod = Array.isArray(plugin) ? plugin[0] : plugin;
  126. if (typeof mod==='string') {
  127. var p = path.resolve(cwd, mod);
  128. mod = require(p);
  129. setHiddenProp(mod, '_original_name', p);
  130. }
  131. return Array.isArray(plugin) ? [mod].concat(plugin.slice(1)) : mod;
  132. });
  133. }
  134. var out = { plugins:plugins };
  135. setHiddenProp(out, 'modify-babel-preset', {
  136. preset: path.dirname(path.resolve(preset)),
  137. modifications: modifications
  138. });
  139. return out;
  140. };