ContextModuleFactory.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. var asyncLib = require("async");
  6. var path = require("path");
  7. var Tapable = require("tapable");
  8. var ContextModule = require("./ContextModule");
  9. var ContextElementDependency = require("./dependencies/ContextElementDependency");
  10. function ContextModuleFactory(resolvers) {
  11. Tapable.call(this);
  12. this.resolvers = resolvers;
  13. }
  14. module.exports = ContextModuleFactory;
  15. ContextModuleFactory.prototype = Object.create(Tapable.prototype);
  16. ContextModuleFactory.prototype.constructor = ContextModuleFactory;
  17. ContextModuleFactory.prototype.create = function(data, callback) {
  18. var module = this;
  19. var context = data.context;
  20. var dependencies = data.dependencies;
  21. var dependency = dependencies[0];
  22. this.applyPluginsAsyncWaterfall("before-resolve", {
  23. context: context,
  24. request: dependency.request,
  25. recursive: dependency.recursive,
  26. regExp: dependency.regExp,
  27. async: dependency.async,
  28. dependencies: dependencies
  29. }, function(err, result) {
  30. if(err) return callback(err);
  31. // Ignored
  32. if(!result) return callback();
  33. var context = result.context;
  34. var request = result.request;
  35. var recursive = result.recursive;
  36. var regExp = result.regExp;
  37. var asyncContext = result.async;
  38. var dependencies = result.dependencies;
  39. var loaders, resource, loadersPrefix = "";
  40. var idx = request.lastIndexOf("!");
  41. if(idx >= 0) {
  42. loaders = request.substr(0, idx + 1);
  43. for(var i = 0; i < loaders.length && loaders[i] === "!"; i++) {
  44. loadersPrefix += "!";
  45. }
  46. loaders = loaders.substr(i).replace(/!+$/, "").replace(/!!+/g, "!");
  47. if(loaders === "") loaders = [];
  48. else loaders = loaders.split("!");
  49. resource = request.substr(idx + 1);
  50. } else {
  51. loaders = [];
  52. resource = request;
  53. }
  54. var resolvers = module.resolvers;
  55. asyncLib.parallel([
  56. function(callback) {
  57. resolvers.context.resolve({}, context, resource, function(err, result) {
  58. if(err) return callback(err);
  59. callback(null, result);
  60. });
  61. },
  62. function(callback) {
  63. asyncLib.map(loaders, function(loader, callback) {
  64. resolvers.loader.resolve({}, context, loader, function(err, result) {
  65. if(err) return callback(err);
  66. callback(null, result);
  67. });
  68. }, callback);
  69. }
  70. ], function(err, result) {
  71. if(err) return callback(err);
  72. module.applyPluginsAsyncWaterfall("after-resolve", {
  73. loaders: loadersPrefix + result[1].join("!") + (result[1].length > 0 ? "!" : ""),
  74. resource: result[0],
  75. recursive: recursive,
  76. regExp: regExp,
  77. async: asyncContext,
  78. dependencies: dependencies,
  79. resolveDependencies: module.resolveDependencies.bind(module)
  80. }, function(err, result) {
  81. if(err) return callback(err);
  82. // Ignored
  83. if(!result) return callback();
  84. return callback(null, new ContextModule(result.resolveDependencies, result.resource, result.recursive, result.regExp, result.loaders, result.async, dependency.chunkName));
  85. });
  86. });
  87. });
  88. };
  89. ContextModuleFactory.prototype.resolveDependencies = function resolveDependencies(fs, resource, recursive, regExp, callback) {
  90. if(!regExp || !resource)
  91. return callback(null, []);
  92. (function addDirectory(directory, callback) {
  93. fs.readdir(directory, function(err, files) {
  94. if(err) return callback(err);
  95. if(!files || files.length === 0) return callback(null, []);
  96. asyncLib.map(files.filter(function(p) {
  97. return p.indexOf(".") !== 0;
  98. }), function(seqment, callback) {
  99. var subResource = path.join(directory, seqment);
  100. fs.stat(subResource, function(err, stat) {
  101. if(err) return callback(err);
  102. if(stat.isDirectory()) {
  103. if(!recursive) return callback();
  104. addDirectory.call(this, subResource, callback);
  105. } else if(stat.isFile()) {
  106. var obj = {
  107. context: resource,
  108. request: "." + subResource.substr(resource.length).replace(/\\/g, "/")
  109. };
  110. this.applyPluginsAsyncWaterfall("alternatives", [obj], function(err, alternatives) {
  111. if(err) return callback(err);
  112. alternatives = alternatives.filter(function(obj) {
  113. return regExp.test(obj.request);
  114. }).map(function(obj) {
  115. var dep = new ContextElementDependency(obj.request);
  116. dep.optional = true;
  117. return dep;
  118. });
  119. callback(null, alternatives);
  120. });
  121. } else callback();
  122. }.bind(this));
  123. }.bind(this), function(err, result) {
  124. if(err) return callback(err);
  125. if(!result) return callback(null, []);
  126. callback(null, result.filter(function(i) {
  127. return !!i;
  128. }).reduce(function(a, i) {
  129. return a.concat(i);
  130. }, []));
  131. });
  132. }.bind(this));
  133. }.call(this, resource, callback));
  134. };