|
49 | 49 | 'fix': 'Fix: ' + 'Make sure that you assign unique module paths using the require.config() method. Take a look at http://requirejs.org/docs/api.html#config for more details\n', |
50 | 50 | 'exiting': 'Result: Did not complete and exiting...' |
51 | 51 | }, |
| 52 | + // Malformed module name |
| 53 | + malformedModuleName: function(moduleName) { |
| 54 | + return 'This module name is malformed: ' + moduleName; |
| 55 | + }, |
| 56 | + // CommonJS converting issues |
| 57 | + 'commonjs': 'There was an error parsing a CommonJS require include. Please create a ticket at https://github.com/gfranko/amdclean/issues', |
52 | 58 | // The user has not supplied the cliean method with any code |
53 | 59 | 'emptyCode': 'There is no code to generate the AST with', |
54 | 60 | // An AST has not been correctly returned by Esprima |
|
92 | 98 | isRequire: function(node) { |
93 | 99 | var expression = node.expression || {}, |
94 | 100 | callee = expression.callee; |
95 | | - return node.type === 'ExpressionStatement' && |
| 101 | + return (node.type === 'ExpressionStatement' && |
96 | 102 | !_.isUndefined(expression) && |
97 | 103 | expression.type === 'CallExpression' && |
98 | 104 | callee.type === 'Identifier' && |
99 | | - callee.name === 'require'; |
| 105 | + callee.name === 'require'); |
| 106 | + }, |
| 107 | + // isCommonJS |
| 108 | + // ---------- |
| 109 | + // Returns if the current AST node is a commonJS require() method call |
| 110 | + // e.g. require('someModule'); |
| 111 | + isCommonJS: function(node) { |
| 112 | + if(!node) return false; |
| 113 | + var callee = node.callee, |
| 114 | + obj = node.object; |
| 115 | + return (publicAPI.isRequireExpression || publicAPI.isRequireMemberExpression(node) || isRequireCallExpression(node)); |
| 116 | + }, |
| 117 | + isRequireExpression: function(node) { |
| 118 | + return (node.type === 'VariableDeclarator' && |
| 119 | + !_.isUndefined(node.init) && |
| 120 | + !_.isUndefined(node.init.type) && |
| 121 | + node.init.type === 'CallExpression' && |
| 122 | + !_.isUndefined(node.init.callee) && |
| 123 | + node.init.callee.name === 'require'); |
| 124 | + }, |
| 125 | + isRequireMemberExpression: function(node) { |
| 126 | + return (node.type === 'VariableDeclarator' && |
| 127 | + !_.isUndefined(node.init) && |
| 128 | + !_.isUndefined(node.init.type) && |
| 129 | + node.init.type === 'MemberExpression' && |
| 130 | + !_.isUndefined(node.init.object) && |
| 131 | + !_.isUndefined(node.init.object.callee) && |
| 132 | + node.init.object.callee.name === 'require'); |
| 133 | + }, |
| 134 | + isRequireCallExpression: function(node) { |
| 135 | + return (node.type === 'VariableDeclarator' && |
| 136 | + !_.isUndefined(node.init) && |
| 137 | + !_.isUndefined(node.init.type) && |
| 138 | + node.init.type === 'CallExpression' && |
| 139 | + !_.isUndefined(node.init.callee) && |
| 140 | + node.init.callee.type === 'MemberExpression' && |
| 141 | + !_.isUndefined(node.init.callee.object) && |
| 142 | + !_.isUndefined(node.init.callee.object.type) && |
| 143 | + node.init.callee.object.type === 'CallExpression' && |
| 144 | + !_.isUndefined(node.init.callee.object['arguments']) && |
| 145 | + !_.isUndefined(node.init.callee.object.callee) && |
| 146 | + node.init.callee.object.callee.name === 'require' && |
| 147 | + !_.isUndefined(node.init.callee.property) && |
| 148 | + !_.isUndefined(node.init.callee.property.name)); |
100 | 149 | }, |
101 | 150 | // isObjectExpression |
102 | 151 | // ------------------ |
|
122 | 171 | containsRelativePath = name.lastIndexOf('/') !== -1; |
123 | 172 | if(containsRelativePath) { |
124 | 173 | moduleName = moduleName.substring(0, lastIndex); |
125 | | - folderName = moduleName.substring((moduleName.lastIndexOf('/') + 1), moduleName.length); |
126 | | - fileName = name.substring((lastIndex + 1), name.length); |
127 | | - return folderName + '_' + fileName; |
| 174 | + folderName = (moduleName.substring((moduleName.lastIndexOf('/') + 1), moduleName.length)).replace(/\W/g, ''); |
| 175 | + fileName = (name.substring((lastIndex + 1), name.length)).replace(/\W/g, ''); |
| 176 | + if(folderName && fileName) { |
| 177 | + return folderName + '_' + fileName; |
| 178 | + } else if(!folderName && fileName) { |
| 179 | + return fileName; |
| 180 | + } else { |
| 181 | + throw new Error(publicAPI.errorMsgs.malformedModuleName(name)); |
| 182 | + } |
128 | 183 | } else { |
129 | 184 | return name; |
130 | 185 | } |
|
150 | 205 | return true; |
151 | 206 | } |
152 | 207 | }, |
| 208 | + // convertCommonJSDeclaration |
| 209 | + // -------------------------- |
| 210 | + // Replaces the CommonJS variable declaration with a variable the same name as the argument |
| 211 | + // e.g. var prop = require('example'); -> var prop = example; |
| 212 | + convertCommonJSDeclaration: function(node) { |
| 213 | + if(!node) return node; |
| 214 | + try { |
| 215 | + if(publicAPI.isRequireExpression(node)) { |
| 216 | + return { |
| 217 | + 'type': 'VariableDeclarator', |
| 218 | + 'id': { |
| 219 | + 'type': 'Identifier', |
| 220 | + 'name': node.id.name |
| 221 | + }, |
| 222 | + 'init': { |
| 223 | + 'type': 'Identifier', |
| 224 | + 'name': publicAPI.normalizeModuleName((node.init['arguments'][0].value) || (node.init['arguments'][0].elements[0].value)) |
| 225 | + } |
| 226 | + }; |
| 227 | + } else if(publicAPI.isRequireMemberExpression(node)) { |
| 228 | + return { |
| 229 | + 'type': 'VariableDeclarator', |
| 230 | + 'id': { |
| 231 | + 'type': 'Identifier', |
| 232 | + 'name': node.id.name |
| 233 | + }, |
| 234 | + 'init': { |
| 235 | + 'type': 'MemberExpression', |
| 236 | + 'computed': false, |
| 237 | + 'object': { |
| 238 | + 'type': 'Identifier', |
| 239 | + 'name': (function() { |
| 240 | + if(node.init && node.init.object && node.init.object['arguments'] && node.init.object['arguments'][0] && node.init.object['arguments'][0].elements) { |
| 241 | + return publicAPI.normalizeModuleName(node.init.object['arguments'][0].elements[0].value); |
| 242 | + } else { |
| 243 | + return publicAPI.normalizeModuleName(node.init.object['arguments'][0].value); |
| 244 | + } |
| 245 | + }()) |
| 246 | + }, |
| 247 | + 'property': { |
| 248 | + 'type': 'Identifier', |
| 249 | + 'name': node.init.property.name |
| 250 | + } |
| 251 | + } |
| 252 | + }; |
| 253 | + } else if(publicAPI.isRequireCallExpression(node)) { |
| 254 | + return { |
| 255 | + 'type': 'VariableDeclarator', |
| 256 | + 'id': { |
| 257 | + 'type': 'Identifier', |
| 258 | + 'name': node.id.name |
| 259 | + }, |
| 260 | + 'init': { |
| 261 | + 'type': 'CallExpression', |
| 262 | + 'callee': { |
| 263 | + 'type': 'MemberExpression', |
| 264 | + 'computed': false, |
| 265 | + 'object': { |
| 266 | + 'type': 'Identifier', |
| 267 | + 'name': (function() { |
| 268 | + if(node.init && node.init.callee && node.init.callee.object && node.init.callee.object['arguments'] && node.init.callee.object['arguments'][0] && node.init.callee.object['arguments'][0].elements) { |
| 269 | + return publicAPI.normalizeModuleName(node.init.callee.object['arguments'][0].elements[0].value); |
| 270 | + } else { |
| 271 | + return publicAPI.normalizeModuleName(node.init.callee.object['arguments'][0].value); |
| 272 | + } |
| 273 | + }()) |
| 274 | + }, |
| 275 | + 'property': { |
| 276 | + 'type': 'Identifier', |
| 277 | + 'name': node.init.callee.property.name |
| 278 | + } |
| 279 | + }, |
| 280 | + 'arguments': node.init['arguments'] |
| 281 | + } |
| 282 | + }; |
| 283 | + } else { |
| 284 | + return node; |
| 285 | + } |
| 286 | + } catch(e) { |
| 287 | + console.log(publicAPI.errorMsgs.commonjs + '\n\n' + e); |
| 288 | + return node; |
| 289 | + } |
| 290 | + |
| 291 | + }, |
| 292 | + // returnExpressionIdentifier |
| 293 | + // -------------------------- |
| 294 | + // Returns a single identifier |
| 295 | + // e.g. module |
| 296 | + returnExpressionIdentifier: function(name) { |
| 297 | + return { |
| 298 | + 'type': 'ExpressionStatement', |
| 299 | + 'expression': { |
| 300 | + 'type': 'Identifier', |
| 301 | + 'name': name |
| 302 | + } |
| 303 | + }; |
| 304 | + }, |
153 | 305 | // convertToObjectDeclaration |
154 | 306 | // -------------------------- |
155 | 307 | // Returns an object variable declaration |
156 | | - // ( e.g. var example = { exampleProp: true } ) |
| 308 | + // e.g. var example = { exampleProp: true } |
157 | 309 | convertToObjectDeclaration: function(obj) { |
158 | 310 | var node = obj.node, |
159 | 311 | moduleName = obj.moduleName, |
|
176 | 328 | // convertToIIFE |
177 | 329 | // ------------- |
178 | 330 | // Returns an IIFE |
179 | | - // ( e.g. (function() { }()) ) |
| 331 | + // e.g. (function() { }()) |
180 | 332 | convertToIIFE: function(obj) { |
181 | 333 | var callbackFuncParams = obj.callbackFuncParams, |
182 | 334 | callbackFunc = obj.callbackFunc, |
|
202 | 354 | // convertToIIFEDeclaration |
203 | 355 | // ------------------------ |
204 | 356 | // Returns a function expression that is executed immediately |
205 | | - // ( e.g. var example = function(){}() ) |
| 357 | + // e.g. var example = function(){}() |
206 | 358 | convertToIIFEDeclaration: function(obj) { |
207 | 359 | var moduleName = obj.moduleName, |
208 | 360 | callbackFuncParams = obj.callbackFuncParams, |
|
248 | 400 | isRequire = obj.isRequire, |
249 | 401 | node = obj.node, |
250 | 402 | moduleName = obj.moduleName, |
| 403 | + dependencies = obj.dependencies, |
| 404 | + depLength = dependencies.length, |
| 405 | + dependencyNames = (function() { |
| 406 | + var deps = [], |
| 407 | + iterator = -1; |
| 408 | + while(++iterator < depLength) { |
| 409 | + deps.push({ type: 'Identifier', name: publicAPI.normalizeModuleName(dependencies[iterator]) }); |
| 410 | + } |
| 411 | + return deps; |
| 412 | + }()), |
251 | 413 | callbackFunc = obj.moduleReturnValue, |
252 | 414 | callbackFuncParams = (function() { |
253 | 415 | var deps = [], |
| 416 | + iterator = -1, |
| 417 | + currentParam, |
254 | 418 | cbParams = callbackFunc.params || []; |
255 | | - _.each(cbParams, function(currentParam) { |
256 | | - deps.push({ 'type': 'Identifier', 'name': currentParam.name }); |
257 | | - }); |
| 419 | + while(++iterator < depLength) { |
| 420 | + currentParam = cbParams[iterator]; |
| 421 | + if(currentParam) { |
| 422 | + deps.push({ 'type': 'Identifier', 'name': currentParam.name }); |
| 423 | + } else { |
| 424 | + deps.push({ 'type': 'Identifier', 'name': dependencyNames[iterator].name }); |
| 425 | + } |
| 426 | + } |
258 | 427 | return deps; |
259 | | - }()), |
260 | | - dependencies = obj.dependencies, |
261 | | - dependencyNames = (function() { |
262 | | - var arr = [], names = dependencies; |
263 | | - _.each(callbackFuncParams, function(currentCallbackFuncParam, iterator) { |
264 | | - arr.push({ type: 'Identifier', name: publicAPI.normalizeModuleName(names[iterator]) }); |
265 | | - }); |
266 | | - return arr; |
267 | 428 | }()); |
268 | 429 | if(isDefine) { |
269 | 430 | return publicAPI.convertToIIFEDeclaration({ |
|
324 | 485 | return publicAPI.convertToFunctionExpression(params); |
325 | 486 | } else { |
326 | 487 | // Remove the require include statement from the source |
327 | | - return { type: 'EmptyStatement', expression: {} }; |
| 488 | + return { type: 'EmptyStatement' }; |
328 | 489 | } |
329 | 490 | } |
330 | 491 | } else { |
|
401 | 562 | ast = publicAPI.traverseAndUpdateAst({ |
402 | 563 | ast: publicAPI.createAst(code) |
403 | 564 | }); |
404 | | - // Removes all empty statements from the source so that there are no single semicolons |
| 565 | + // Removes all empty statements from the source so that there are no single semicolons and |
| 566 | + // Make sure that all require() CommonJS calls are converted |
405 | 567 | if(ast && _.isArray(ast.body)) { |
406 | | - _.each(ast.body, function(currentNode, iterator) { |
407 | | - if(currentNode === undefined || currentNode.type === 'EmptyStatement') { |
408 | | - ast.body.splice(iterator, 1); |
| 568 | + estraverse.replace(ast, { |
| 569 | + enter: function(node, parent) { |
| 570 | + if(node === undefined || node.type === 'EmptyStatement') { |
| 571 | + _.each(parent.body, function(currentNode, iterator) { |
| 572 | + if(currentNode === undefined || currentNode.type === 'EmptyStatement') { |
| 573 | + parent.body.splice(iterator, 1); |
| 574 | + } |
| 575 | + }); |
| 576 | + } else if(node.type === 'VariableDeclaration' && Array.isArray(node.declarations)) { |
| 577 | + _.each(node.declarations, function(currentDeclaration, iterator) { |
| 578 | + if(publicAPI.isCommonJS(currentDeclaration)) { |
| 579 | + node.declarations[iterator] = publicAPI.convertCommonJSDeclaration(currentDeclaration); |
| 580 | + } |
| 581 | + }); |
| 582 | + return node; |
| 583 | + } |
| 584 | + |
409 | 585 | } |
410 | 586 | }); |
411 | 587 | } |
|
0 commit comments