diff --git a/lib/index.js b/lib/index.js index ab83ec5..a733cec 100644 --- a/lib/index.js +++ b/lib/index.js @@ -14,7 +14,28 @@ var RequireHeaderDependency = require("webpack/lib/dependencies/RequireHeaderDep var AngularModuleDependency = require('./AngularModuleDependency'); var AngularModuleDefinition = require('./AngularModuleDefinition'); -function AngularPlugin() { +//options provided will apply to all instances of AngularPlugin, but +//usage with webpack requires only a single instance. This eases +//access to these options in contexts without access to AngularPlugin +//during compilation, below. +var noParse, verbose; +function AngularPlugin(options) { + options = options || {}; + + //should we print information to the console about angular + //modules and dependencies as we find/process them? + verbose = options.verbose || false; + + //specify angular module dependencies that should be ignored: + + //a dictionary where the keys are exact angular modules names (or "*", + //for matching all modules) where the value is either one, or a list, + //of strings and/or regexes that, if they match a dependency specified on an + //angular module definition, will be ignored as a dependency to be + //handled by webpack. This is essential when porting projects to + //webpack whose source may not change to accomodate webpack conventions + //as is the case, for instance, with angular-ui-bootstrap builtin templates. + noParse = options.noParse || {}; } module.exports = AngularPlugin; @@ -84,10 +105,28 @@ AngularPlugin.prototype = { addAngularVariable: function(parser) { return ModuleParserHelpers.addParsedVariable(parser, 'angular', "require('exports?window.angular!angular')"); }, - + + lastModule:false, + lastContext:false, + lastRawRequest:false, + // Each call to `angular.module()` is analysed here parseModuleCall: function(parser, expr){ this.addAngularVariable(parser); + + if(verbose && this.lastContext != parser.state.current.context){ + console.log("\ncd", parser.state.current.context); + this.lastContext = parser.state.current.context; + } + + if(verbose && this.lastRawRequest != parser.state.current.rawRequest){ + console.log("\n require(\""+parser.state.current.rawRequest+"\")"); + this.lastRawRequest = parser.state.current.rawRequest; + } + + this.lastModule = expr.arguments[0].value; + verbose && console.log(" angular.module(\""+this.lastModule+"\")"); + switch(expr.arguments.length){ case 1: return this._parseModuleCallSingleArgument(parser, expr); case 2: return this._parseModuleCallTwoArgument(parser, expr); @@ -214,7 +253,7 @@ AngularPlugin.prototype = { parser.state.current.addDependency(dep); return true; }, - + // A dependency (module) has been found _addDependency: function(parser, expr, param){ if( param.isConditional() ){ @@ -232,13 +271,32 @@ AngularPlugin.prototype = { return true; } if( param.isString() ){ - var dep; - var localModule = LocalModulesHelpers.getLocalModule(parser.state, param.string); + var dep, localModule; + + //see JROBEY comment above; skip paths that refer to templates that defy dependency "rules". + for(var key in noParse){ + if(key == '*' || key == this.lastModule){ + var to_match = noParse[key] instanceof Array ? noParse[key] : [noParse[key]]; + + for(var i = 0; i !== to_match.length; i ++){ + var consider = to_match[i]; + + if((consider.exec && consider.exec(param.string)) || param.string == consider){ + verbose && console.log(" (skip", param.string+")"); + return true; + } + } + } + } + + localModule = LocalModulesHelpers.getLocalModule(parser.state, param.string); if( localModule ) { return true; } + dep = new AngularModuleDependency(param.string, param.range); dep.loc = param.loc; + verbose && param.string !== this.lastModule && console.log(" ", param.string); parser.state.current.addDependency(dep); return true; }