mirror of https://github.com/webpack/webpack.git
				
				
				
			
		
			
				
	
	
		
			259 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
			
		
		
	
	
			259 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
| /*
 | |
| 	MIT License http://www.opensource.org/licenses/mit-license.php
 | |
| 	Author Tobias Koppers @sokra
 | |
| */
 | |
| var path = require("path");
 | |
| var fs = require("fs");
 | |
| 
 | |
| // http://nodejs.org/docs/v0.4.8/api/all.html#all_Together...
 | |
| 
 | |
| 
 | |
| function resolve(context, identifier, options, type, callback) {
 | |
| 	function finalResult(err, absoluteFilename) {
 | |
| 		if(err) {
 | |
| 			callback("Module \"" + identifier + "\" not found in context \"" +
 | |
| 						context + "\"\n  " + err);
 | |
| 			return;
 | |
| 		}
 | |
| 		callback(null, absoluteFilename);
 | |
| 	}
 | |
| 	var identArray = split(identifier);
 | |
| 	var contextArray = split(context);
 | |
| 	while(options.alias[identArray[0]]) {
 | |
| 		var old = identArray[0];
 | |
| 		identArray[0] = options.alias[identArray[0]];
 | |
| 		identArray = split(path.join.apply(path, identArray));
 | |
| 		if(identArray[0] === old)
 | |
| 			break;
 | |
| 	}
 | |
| 	if(identArray[0] === "." || identArray[0] === ".." || identArray[0] === "" || identArray[0].match(/^[A-Z]:$/i)) {
 | |
| 		var pathname = identArray[0][0] === "." ? join(contextArray, identArray) : join(identArray, []);
 | |
| 		if(type === "context") {
 | |
| 			fs.stat(pathname, function(err, stat) {
 | |
| 				if(err) {
 | |
| 					finalResult(err);
 | |
| 					return;
 | |
| 				}
 | |
| 				if(!stat.isDirectory()) {
 | |
| 					finalResult("Context \"" + identifier + "\" in not a directory");
 | |
| 					return;
 | |
| 				}
 | |
| 				callback(null, pathname);
 | |
| 			});
 | |
| 		} else {
 | |
| 			loadAsFile(pathname, options, type, function(err, absoluteFilename) {
 | |
| 				if(err) {
 | |
| 					loadAsDirectory(pathname, options, type, finalResult);
 | |
| 					return;
 | |
| 				}
 | |
| 				callback(null, absoluteFilename);
 | |
| 			});
 | |
| 		}
 | |
| 	} else {
 | |
| 		loadNodeModules(contextArray, identArray, options, type, finalResult);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| function doResolve(context, identifier, options, type, callback) {
 | |
| 	if(!callback) {
 | |
| 		callback = options;
 | |
| 		options = {};
 | |
| 	}
 | |
| 	if(!options)
 | |
| 		options = {};
 | |
| 	if(!options.extensions)
 | |
| 		options.extensions = ["", ".webpack.js", ".web.js", ".js"];
 | |
| 	if(!options.loaders)
 | |
| 		options.loaders = [];
 | |
| 	if(!options.postfixes)
 | |
| 		options.postfixes = ["", "-webpack", "-web"];
 | |
| 	if(!options.loaderExtensions)
 | |
| 		options.loaderExtensions = [".webpack-web-loader.js", ".webpack-loader.js", ".web-loader.js", ".loader.js", "", ".js"];
 | |
| 	if(!options.loaderPostfixes)
 | |
| 		options.loaderPostfixes = ["-webpack-web-loader", "-webpack-loader", "-web-loader", "-loader", ""];
 | |
| 	if(!options.paths)
 | |
| 		options.paths = [];
 | |
| 	if(!options.alias)
 | |
| 		options.alias = {};
 | |
| 	var identifiers = identifier.replace(/^!|!$/g, "").replace(/!!/g, "!").split(/!/g);
 | |
| 	var resource = identifiers.pop();
 | |
| 	resolve(context, resource, options, type, function(err, resource) {
 | |
| 		if(err) return callback(err);
 | |
| 		if(identifier.indexOf("!") === -1) {
 | |
| 			for(var i = 0; i < options.loaders.length; i++) {
 | |
| 				var line = options.loaders[i];
 | |
| 				if(line.test.test(resource)) {
 | |
| 					Array.prototype.push.apply(identifiers, line.loader.split(/!/g));
 | |
| 					break;
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 		var errors = [];
 | |
| 		var count = identifiers.length;
 | |
| 		function endOne() {
 | |
| 			count--;
 | |
| 			if(count === 0) {
 | |
| 				if(errors.length > 0) {
 | |
| 					callback(errors.join("\n"));
 | |
| 					return;
 | |
| 				}
 | |
| 				identifiers.push(resource);
 | |
| 				callback(null, identifiers.join("!"));
 | |
| 			}
 | |
| 		}
 | |
| 		if(count == 0) endOne(count++);
 | |
| 		identifiers.forEach(function(ident, index) {
 | |
| 			resolve(context, ident, options, "loader", function(err, filename) {
 | |
| 				if(err) {
 | |
| 					errors.push(err);
 | |
| 				} else {
 | |
| 					identifiers[index] = filename;
 | |
| 				}
 | |
| 				endOne()
 | |
| 			});
 | |
| 		});
 | |
| 	});
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * context: absolute filename of current file
 | |
|  * identifier: module to find
 | |
|  * options:
 | |
|  *   paths: array of lookup paths
 | |
|  * callback: function(err, absoluteFilename)
 | |
|  */
 | |
| module.exports = function(context, identifier, options, callback) {
 | |
| 	return doResolve(context, identifier, options, "normal", callback);
 | |
| }
 | |
| 
 | |
| module.exports.context = function(context, identifier, options, callback) {
 | |
| 	return doResolve(context, identifier, options, "context", callback);
 | |
| }
 | |
| 
 | |
| 
 | |
| function split(a) {
 | |
| 	return a.split(/[\/\\]/g);
 | |
| }
 | |
| 
 | |
| function join(a, b) {
 | |
| 	var c = [];
 | |
| 	a.forEach(function(x) { c.push(x) });
 | |
| 	b.forEach(function(x) { c.push(x) });
 | |
| 	if(c[0] === "")
 | |
| 		c[0] = "/";
 | |
| 	return path.join.apply(path, c);
 | |
| }
 | |
| 
 | |
| function loadAsFile(filename, options, type, callback) {
 | |
| 	var pos = -1, result = "NOT SET";
 | |
| 	var extensions = type === "loader" ? options.loaderExtensions : options.extensions;
 | |
| 	function tryCb(err, stats) {
 | |
| 		if(err || !stats || !stats.isFile()) {
 | |
| 			pos++;
 | |
| 			if(pos >= extensions.length) {
 | |
| 				callback(err || "Isn't a file");
 | |
| 				return;
 | |
| 			}
 | |
| 			fs.stat(result = filename + extensions[pos], tryCb);
 | |
| 			return;
 | |
| 		}
 | |
| 		if(!result) throw new Error("no result");
 | |
| 		callback(null, result);
 | |
| 	}
 | |
| 	tryCb(true);
 | |
| }
 | |
| 
 | |
| function loadAsDirectory(dirname, options, type, callback) {
 | |
| 	var packageJsonFile = join(split(dirname), ["package.json"]);
 | |
| 	fs.stat(packageJsonFile, function(err, stats) {
 | |
| 		var mainModule = "index";
 | |
| 		if(!err && stats.isFile()) {
 | |
| 			fs.readFile(packageJsonFile, "utf-8", function(err, content) {
 | |
| 				if(err) {
 | |
| 					callback(err);
 | |
| 					return;
 | |
| 				}
 | |
| 				content = JSON.parse(content);
 | |
| 				if(content.webpackLoader && type === "loader")
 | |
| 					mainModule = content.webpackLoader;
 | |
| 				else if(content.webpack)
 | |
| 					mainModule = content.webpack;
 | |
| 				else if(content.browserify)
 | |
| 					mainModule = content.browserify;
 | |
| 				else if(content.main)
 | |
| 					mainModule = content.main;
 | |
| 				loadAsFile(join(split(dirname), [mainModule]), options, type, callback);
 | |
| 			});
 | |
| 		} else
 | |
| 			loadAsFile(join(split(dirname), [mainModule]), options, type, callback);
 | |
| 	});
 | |
| }
 | |
| 
 | |
| function loadNodeModules(context, identifier, options, type, callback) {
 | |
| 	var moduleName = identifier.shift();
 | |
| 	var postfixes = type === "loader" ? options.loaderPostfixes : options.postfixes;
 | |
| 	nodeModulesPaths(context, options, function(err, paths) {
 | |
| 		var dirs = [];
 | |
| 		paths.forEach(function(path) {
 | |
| 			postfixes.forEach(function(postfix) {
 | |
| 				dirs.push(join(split(path), [moduleName+postfix]));
 | |
| 			});
 | |
| 		});
 | |
| 		function tryDir(dir) {
 | |
| 			var pathname = join(split(dir), identifier);
 | |
| 			if(type === "context") {
 | |
| 				fs.stat(pathname, function(err, stat) {
 | |
| 					if(err || !stat.isDirectory()) {
 | |
| 						if(dirs.length === 0) {
 | |
| 							callback("no directory in any path of paths");
 | |
| 							return;
 | |
| 						}
 | |
| 						tryDir(dirs.shift());
 | |
| 						return;
 | |
| 					}
 | |
| 					callback(null, pathname);
 | |
| 				});
 | |
| 			} else {
 | |
| 				loadAsFile(pathname, options, type, function(err, absoluteFilename) {
 | |
| 					if(err) {
 | |
| 						loadAsDirectory(pathname, options, type, function(err, absoluteFilename) {
 | |
| 							if(err) {
 | |
| 								if(dirs.length === 0) {
 | |
| 									callback("no module in any path of paths");
 | |
| 									return;
 | |
| 								}
 | |
| 								tryDir(dirs.shift());
 | |
| 								return;
 | |
| 							}
 | |
| 							callback(null, absoluteFilename);
 | |
| 						});
 | |
| 						return;
 | |
| 					}
 | |
| 					callback(null, absoluteFilename);
 | |
| 				});
 | |
| 			}
 | |
| 		}
 | |
| 		tryDir(dirs.shift());
 | |
| 	});
 | |
| }
 | |
| 
 | |
| function nodeModulesPaths(context, options, callback) {
 | |
| 	var parts = context;
 | |
| 	var rootNodeModules = parts.indexOf("node_modules");
 | |
| 	var rootWebModules = parts.indexOf("web_modules");
 | |
| 	var root = 0;
 | |
| 	if(rootWebModules != -1 && rootNodeModules != -1)
 | |
| 		root = Math.min(rootWebModules, rootNodeModules)-1;
 | |
| 	else if(rootWebModules != -1 || rootNodeModules != -1)
 | |
| 		root = Math.max(rootWebModules, rootNodeModules)-1;
 | |
| 	var dirs = [];
 | |
| 	options.paths.forEach(function(path) { dirs.push(path) });
 | |
| 	for(var i = parts.length; i > root; i--) {
 | |
| 		if(parts[i-1] === "node_modules" || parts[i-1] === "web_modules")
 | |
| 			continue;
 | |
| 		var part = parts.slice(0, i);
 | |
| 		dirs.push(join(part, ["web_modules"]));
 | |
| 		dirs.push(join(part, ["node_modules"]));
 | |
| 	}
 | |
| 	callback(null, dirs);
 | |
| } |