serialize.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. var fs = require('fs');
  2. var path = require('path');
  3. var requireRelative = require('require-relative');
  4. var normalizePreset = require('./normalize-preset');
  5. var join = path.join;
  6. var dirname = path.dirname;
  7. var relative = path.relative;
  8. function getModulePath(filepath) {
  9. return filepath.replace(/(.*([\\/]node_modules|\.\.)[\\/](@[^\\/]+[\\/])?[^\\/]+)([\\/].*)?$/g, '$1')
  10. }
  11. // Attempt to require a module, returning false on error
  12. function req(name) {
  13. try {
  14. return require(name);
  15. } catch (err) {
  16. return false;
  17. }
  18. }
  19. // Attempt to resolve a module, returning `undefined` on error
  20. function resolve(name, relativeTo) {
  21. var path = false;
  22. try {
  23. path = requireRelative.resolve(name, relativeTo);
  24. } catch (err) {
  25. console.log('resolve failed for "'+name+'": '+err);
  26. }
  27. return path;
  28. }
  29. // fast npm always use symlink
  30. // and it resulted in module duplicated
  31. // or alias
  32. function fillAliasMap(path, list, map) {
  33. return list.reduce(function (symlinkedList, mod) {
  34. var realPath = relative(path, fs.realpathSync(join(path, mod)));
  35. if (realPath !== mod) {
  36. symlinkedList[realPath] = (mod);
  37. }
  38. return symlinkedList;
  39. }, map || {});
  40. }
  41. // Get a list of child module names for the given module path
  42. function getChildren(path, type, alias) {
  43. var modules;
  44. try {
  45. modules = fs.readdirSync(join(path, 'node_modules'));
  46. } catch (err) {
  47. path = path.replace(/([\\/]node_modules)([\\/].*)?$/g, '$1');
  48. modules = fs.readdirSync(path);
  49. }
  50. var children = (modules || [])
  51. .filter( realFile )
  52. .sort( reverseSorter(type==='plugin' ? isPlugin : isPreset) );
  53. fillAliasMap(path, children, alias);
  54. return children;
  55. }
  56. // is a filename an actual file
  57. function realFile(f) {
  58. return f && f.charAt(0)!=='.';
  59. }
  60. // ascending sort based on the truthiness of a function
  61. function reverseSorter(comparison) {
  62. return function(a, b) {
  63. var ca = comparison(a),
  64. cb = comparison(b);
  65. return ca===cb ? 0 : (ca ? 1 : cb ? -1 : 0);
  66. }
  67. }
  68. function isPreset(name) { return name && name.match(/^babel\-preset\-/g); }
  69. function isPlugin(name) { return name && name.match(/^babel\-plugin\-/g); }
  70. // find the matching module *instance* in a list of module paths, remove and return it
  71. function findAndRemove(preset, path, list) {
  72. for (var i=list.length; i--; ) {
  73. var p = resolve(list[i], path),
  74. v = p && req(p);
  75. if (v && v===preset) {
  76. list.splice(i, 1);
  77. return p;
  78. }
  79. }
  80. }
  81. /** Resolve & serialize a Babel preset to a filename-based representation.
  82. * Nested filepaths are relative to `relativeTo` if specified.
  83. * Presets referenced as Strings (uncommon) are treated as dependencies of the preset that returned them.
  84. */
  85. function loadPreset(name, opts, relativeTo) {
  86. var path = resolve(name, relativeTo),
  87. mod = normalizePreset(path && req(path), null, opts.options);
  88. if (!mod) throw new Error('Preset "'+name+'" not found.');
  89. path = dirname(path);
  90. var out = {
  91. alias: {}
  92. };
  93. if (mod.presets) {
  94. var availablePresets = getChildren(path, 'preset', out.alias);
  95. out.presets = mod.presets.map(function(preset) {
  96. if (typeof preset!=='string') {
  97. preset = findAndRemove(preset, path, availablePresets);
  98. }
  99. return loadPreset(preset, opts, path);
  100. });
  101. }
  102. if (mod.plugins) {
  103. var availablePlugins = getChildren(path, 'plugin', out.alias);
  104. out.plugins = mod.plugins.map(function(plugin) {
  105. var name = Array.isArray(plugin) ? plugin[0] : plugin;
  106. if (typeof name!=='string') {
  107. if (name._original_name) {
  108. // console.log('using _original_name: ', name._original_name);
  109. name = name._original_name;
  110. }
  111. else {
  112. name = findAndRemove(name, path, availablePlugins);
  113. }
  114. }
  115. if (!name) return plugin;
  116. name = resolve(name, path);
  117. name = getModulePath(name);
  118. if (opts) {
  119. if (opts.cwd) name = relative(opts.cwd, name);
  120. if (opts.transform) name = opts.transform(name);
  121. }
  122. return Array.isArray(plugin) ? [name].concat(plugin.slice(1)) : name;
  123. });
  124. }
  125. return out;
  126. }
  127. module.exports = loadPreset;