Skip to content

Commit 1f2f1ef

Browse files
committed
Merge branch 'dev'
* dev: Re: #35, #32 - Releasing AMDClean v1.3.0 Fixed typo #33 - Added ability for relative module resolution.
2 parents 5a0d3f6 + 6004e6a commit 1f2f1ef

File tree

4 files changed

+113
-15
lines changed

4 files changed

+113
-15
lines changed

build/amdclean.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "amdclean",
3-
"version": "1.2.1",
3+
"version": "1.3.0",
44
"description": "A build tool that converts AMD code to standard JavaScript",
55
"main": "./src/amdclean",
66
"repository": {

src/amdclean.js

Lines changed: 75 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/*! amdclean - v1.2.1 - 2014-02-17
1+
/*! amdclean - v1.3.0 - 2014-03-03
22
* http://gregfranko.com/amdclean
33
* Copyright (c) 2014 Greg Franko; Licensed MIT*/
44

@@ -74,7 +74,7 @@
7474
// The Public API object
7575
publicAPI = {
7676
// Current project version number
77-
'VERSION': '1.2.1',
77+
'VERSION': '1.3.0',
7878
// Default Options
7979
'defaultOptions': {
8080
// The source code you would like to be 'cleaned'
@@ -559,16 +559,61 @@
559559
}());
560560
return updatedNode;
561561
},
562+
// isRelativeFilePath
563+
// ------------------
564+
// Returns a boolean that determines if the file path provided is a relative file path
565+
// e.g. ../exampleModule -> true
566+
isRelativeFilePath: function(path) {
567+
var segments = path.split('/');
568+
569+
return segments.length !== -1 && (segments[0] === '.' || segments[0] === '..');
570+
},
571+
// normalizeDependencyName
572+
// -----------------------
573+
// Returns a normalized dependency name that handles relative file paths
574+
'normalizeDependencyName': function(moduleId, dep) {
575+
if(!moduleId || !dep || !publicAPI.isRelativeFilePath(dep)) {
576+
return dep;
577+
}
578+
579+
var normalizePath = function(path) {
580+
var segments = path.split('/'),
581+
normalizedSegments;
582+
583+
normalizedSegments = _.reduce(segments, function(memo, segment) {
584+
switch(segment) {
585+
case '.':
586+
break;
587+
case '..':
588+
memo.pop();
589+
break;
590+
default:
591+
memo.push(segment);
592+
}
593+
594+
return memo;
595+
}, []);
596+
return normalizedSegments.join('/');
597+
},
598+
baseName = function(path) {
599+
var segments = path.split('/');
600+
601+
segments.pop();
602+
return segments.join('/');
603+
};
604+
return normalizePath([baseName(moduleId), dep].join('/'));
605+
},
562606
// convertToFunctionExpression
563607
// ---------------------------
564608
// Returns either an IIFE or variable declaration.
565-
// Internally calls either convertToIIFE() or convertToIIFEDeclaration().
609+
// Internally calls either convertToIIFE() or convertToIIFEDeclaration()
566610
'convertToFunctionExpression': function(obj) {
567611
var isDefine = obj.isDefine,
568612
isRequire = obj.isRequire,
569613
isOptimized = false,
570614
node = obj.node,
571615
moduleName = obj.moduleName,
616+
moduleId = obj.moduleId,
572617
dependencies = obj.dependencies,
573618
depLength = dependencies.length,
574619
options = publicAPI.options,
@@ -577,7 +622,7 @@
577622
iterator = -1,
578623
currentName;
579624
while(++iterator < depLength) {
580-
currentName = dependencies[iterator];
625+
currentName = publicAPI.normalizeDependencyName(moduleId, dependencies[iterator]);
581626
if(options.globalObject === true && options.globalObjectName && currentName !== '{}') {
582627
deps.push({
583628
'type': 'MemberExpression',
@@ -717,6 +762,7 @@
717762
args,
718763
dependencies,
719764
moduleReturnValue,
765+
moduleId,
720766
params,
721767
isDefine = publicAPI.isDefine(node),
722768
isRequire = publicAPI.isRequire(node),
@@ -778,10 +824,12 @@
778824
return depNames;
779825
}());
780826
moduleReturnValue = isRequire ? args[1] : args[args.length - 1];
781-
moduleName = publicAPI.normalizeModuleName(node.expression['arguments'][0].value);
827+
moduleId = node.expression['arguments'][0].value;
828+
moduleName = publicAPI.normalizeModuleName(moduleId);
782829
params = {
783830
node: node,
784831
moduleName: moduleName,
832+
moduleId: moduleId,
785833
dependencies: dependencies,
786834
moduleReturnValue: moduleReturnValue,
787835
isDefine: isDefine,
@@ -968,6 +1016,7 @@
9681016
if(ast && _.isArray(ast.body)) {
9691017
estraverse.replace(ast, {
9701018
enter: function(node, parent) {
1019+
var normalizedModuleName;
9711020
if(node === undefined || node.type === 'EmptyStatement') {
9721021
_.each(parent.body, function(currentNode, iterator) {
9731022
if(currentNode === undefined || currentNode.type === 'EmptyStatement') {
@@ -976,10 +1025,27 @@
9761025
});
9771026
} else if(publicAPI.isRequireExpression(node)) {
9781027
if(node['arguments'] && node['arguments'][0] && node['arguments'][0].value) {
979-
return {
980-
'type': 'Identifier',
981-
'name': publicAPI.normalizeModuleName(node['arguments'][0].value)
982-
};
1028+
normalizedModuleName = publicAPI.normalizeModuleName(node['arguments'][0].value);
1029+
if(options.globalObject === true && (options.globalObjectName && _.isString(options.globalObjectName) && options.globalObjectName.length)) {
1030+
return {
1031+
'type': 'MemberExpression',
1032+
'computed': true,
1033+
'object': {
1034+
'type': 'Identifier',
1035+
'name': options.globalObjectName
1036+
},
1037+
'property': {
1038+
'type': 'Literal',
1039+
'value': normalizedModuleName,
1040+
'raw': normalizedModuleName
1041+
}
1042+
};
1043+
} else {
1044+
return {
1045+
'type': 'Identifier',
1046+
'name': normalizedModuleName
1047+
};
1048+
}
9831049
} else {
9841050
return node;
9851051
}

test/specs/convert.js

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,30 @@ describe('amdclean specs', function() {
3737
expect(cleanedCode).toBe(standardJavaScript);
3838
});
3939

40+
it('should correctly normalize relative file paths dependencies', function() {
41+
var AMDcode = "define('./modules/example', ['./example1', './example2', '../example3'], function(one, two, three) {var test = true;});",
42+
cleanedCode = amdclean.clean({ code: AMDcode, escodegen: { format: { compact: true } } }),
43+
standardJavaScript = "var modules_example=function (one,two,three){var test=true;}(modules_example1,modules_example2,example3);";
44+
45+
expect(cleanedCode).toBe(standardJavaScript);
46+
});
47+
48+
it('should correctly normalize relative file paths dependencies with the globalObject option', function() {
49+
var AMDcode = "define('./modules/example', ['./example1', './example2', '../example3'], function(one, two, three) {var test = true;});",
50+
cleanedCode = amdclean.clean({ globalObject: true, rememberGlobalObject: false, code: AMDcode, escodegen: { format: { compact: true } } }),
51+
standardJavaScript = "var amdclean={};amdclean['modules_example']=function (one,two,three){var test=true;}(amdclean['modules_example1'],amdclean['modules_example2'],amdclean['example3']);";
52+
53+
expect(cleanedCode).toBe(standardJavaScript);
54+
});
55+
56+
it('should correctly normalize multi-level relative file paths dependencies', function() {
57+
var AMDcode = "define('./foo/prototype/subModule/myModule', ['example1','example2', '/anotherModule/example3', '../../example4','../anotherModule/example5'], function(one, two, three, four, five) { var test = true;});",
58+
cleanedCode = amdclean.clean({ code: AMDcode, escodegen: { format: { compact: true } } }),
59+
standardJavaScript = "var foo_prototype_subModule_myModule=function (one,two,three,four,five){var test=true;}(example1,example2,anotherModule_example3,foo_example4,foo_prototype_anotherModule_example5);";
60+
61+
expect(cleanedCode).toBe(standardJavaScript);
62+
});
63+
4064
it('should correctly normalize multi-level relative file paths', function() {
4165
var AMDcode = "define('./foo/prototype/commonMethodName.js', ['example1', 'example2'], function(one, two) { var test = true;});",
4266
cleanedCode = amdclean.clean({ code: AMDcode, escodegen: { format: { compact: true } } }),
@@ -119,8 +143,8 @@ describe('amdclean specs', function() {
119143

120144
it('should support storing modules inside of a global object', function() {
121145
var AMDcode = "define('foo', ['require', 'exports', './bar'], function(require, exports){exports.bar = require('./bar');});",
122-
cleanedCode = amdclean.clean({ globalObject: true, globalObjectName: 'yeabuddy', code: AMDcode, escodegen: { format: { compact: true } } }),
123-
standardJavaScript = "var yeabuddy={};yeabuddy['foo']=function (require,exports,bar){exports.bar=bar;return exports;}({},{},yeabuddy['bar']);";
146+
cleanedCode = amdclean.clean({ globalObject: true, rememberGlobalObject: false, globalObjectName: 'yeabuddy', code: AMDcode, escodegen: { format: { compact: true } } }),
147+
standardJavaScript = "var yeabuddy={};yeabuddy['foo']=function (require,exports,bar){exports.bar=yeabuddy['bar'];return exports;}({},{},yeabuddy['bar']);";
124148

125149
expect(cleanedCode).toBe(standardJavaScript);
126150
});
@@ -337,8 +361,8 @@ describe('amdclean specs', function() {
337361

338362
it('should convert object return values to a global object', function() {
339363
var AMDcode = "define('third', { exampleProp: 'This is an example' });",
340-
cleanedCode = amdclean.clean({ globalObject: true, code: AMDcode, escodegen: { format: { compact: true } } }),
341-
standardJavaScript = "amdclean['third']={exampleProp:'This is an example'};";
364+
cleanedCode = amdclean.clean({ globalObject: true, rememberGlobalObject: false, code: AMDcode, escodegen: { format: { compact: true } } }),
365+
standardJavaScript = "var amdclean={};amdclean['third']={exampleProp:'This is an example'};";
342366

343367
expect(cleanedCode).toBe(standardJavaScript);
344368
});
@@ -355,6 +379,14 @@ describe('amdclean specs', function() {
355379
expect(cleanedCode).toBe(standardJavaScript);
356380
});
357381

382+
it('should convert CommonJS require() calls correctly with the globalObject option', function() {
383+
var AMDcode = "var example = require('anotherModule');",
384+
cleanedCode = amdclean.clean({ code: AMDcode, globalObject: true, rememberGlobalObject: false, escodegen: { format: { compact: true } } }),
385+
standardJavaScript = "var amdclean={};var example=amdclean['anotherModule'];";
386+
387+
expect(cleanedCode).toBe(standardJavaScript);
388+
});
389+
358390
it('should convert CommonJS require() calls with file paths', function() {
359391
var AMDcode = "var example = require('./anotherModule');",
360392
cleanedCode = amdclean.clean({ code: AMDcode, escodegen: { format: { compact: true } } }),

0 commit comments

Comments
 (0)