add amd module formatter #82

This commit is contained in:
Sebastian McKenzie
2014-10-19 17:05:24 +11:00
parent 209093a3f0
commit fceff4b52f
35 changed files with 391 additions and 25 deletions

View File

@@ -123,6 +123,17 @@ File.prototype.generate = function () {
};
File.prototype.generateUid = function (name) {
// replace all non-valid identifiers with dashes
name = name.replace(/[^a-zA-Z0-9]/g, "-");
// remove all dashes and numbers from start of name
name = name.replace(/^[-0-9]+/, "");
// camel case
name = name.replace(/[-_\s]+(.)?/g, function(match, c){
return c ? c.toUpperCase() : "";
});
var uids = this.uids;
var i = uids[name] || 1;

View File

@@ -0,0 +1,106 @@
module.exports = AMDFormatter;
var CommonJSFormatter = require("./common");
var util = require("../util");
var b = require("ast-types").builders;
var _ = require("lodash");
function AMDFormatter(file) {
this.file = file;
this.ids = {};
}
AMDFormatter.prototype.transform = function (ast) {
var program = ast.program;
var body = program.body;
// build an array of module names
var names = [];
_.each(this.ids, function (id, name) {
names.push(b.literal(name));
});
names = b.arrayExpression(names);
// add exports
body.unshift(b.variableDeclaration("var", [
b.variableDeclarator(b.identifier("exports"), b.objectExpression([]))
]));
body.push(b.returnStatement(b.identifier("exports")));
// build up define container
var container = b.functionExpression(null, _.values(this.ids), b.blockStatement(body));
var call = b.callExpression(b.identifier("define"), [names, container]);
program.body = [b.expressionStatement(call)];
};
AMDFormatter.prototype._push = function (node) {
var id = node.source.value;
var ids = this.ids;
if (ids[id]) {
return ids[id];
} else {
return this.ids[id] = b.identifier(this.file.generateUid(id));
}
};
AMDFormatter.prototype.import = function (node, nodes) {
this._push(node);
};
AMDFormatter.prototype.importSpecifier = function (specifier, node, nodes) {
var key = util.getSpecifierName(specifier);
var id = specifier.id;
// import foo from "foo";
if (specifier.default) {
id = b.identifier("default");
}
var ref;
if (specifier.type === "ImportBatchSpecifier") {
// import * as bar from "foo";
ref = this._push(node);
} else {
// import foo from "foo";
ref = b.memberExpression(this._push(node), id, false);
}
nodes.push(b.variableDeclaration("var", [
b.variableDeclarator(key, ref)
]));
};
AMDFormatter.prototype.export = CommonJSFormatter.prototype.export;
AMDFormatter.prototype.exportSpecifier = function (specifier, node, nodes) {
var variableName = util.getSpecifierName(specifier);
if (node.source) {
var object = this._push(node);
if (specifier.type === "ExportBatchSpecifier") {
// export * from "foo";
nodes.push(util.template("exports-wildcard", {
OBJECT: object
}, true));
} else {
// export { foo } from "test";
nodes.push(util.template("exports-assign-key", {
VARIABLE_NAME: variableName.name,
OBJECT: object,
KEY: specifier.id
}, true));
}
} else {
// export { foo };
nodes.push(util.template("exports-assign", {
VALUE: specifier.id,
KEY: variableName
}, true));
}
};

View File

@@ -1,25 +1,21 @@
module.exports = CommonJSModuleFormatter;
module.exports = CommonJSFormatter;
var util = require("../util");
var b = require("recast").types.builders;
var getSpecifierName = function (specifier) {
return specifier.name || specifier.id;
};
function CommonJSModuleFormatter(file) {
function CommonJSFormatter(file) {
this.file = file;
}
CommonJSModuleFormatter.prototype.import = function (node, nodes) {
CommonJSFormatter.prototype.import = function (node, nodes) {
// import "foo";
nodes.push(util.template("require", {
MODULE_NAME: node.source.raw
}, true));
};
CommonJSModuleFormatter.prototype.importSpecifier = function (specifier, node, nodes) {
var variableName = getSpecifierName(specifier);
CommonJSFormatter.prototype.importSpecifier = function (specifier, node, nodes) {
var variableName = util.getSpecifierName(specifier);
// import foo from "foo";
if (specifier.default) {
@@ -32,13 +28,13 @@ CommonJSModuleFormatter.prototype.importSpecifier = function (specifier, node, n
if (specifier.type !== "ImportBatchSpecifier") templateName += "-key";
nodes.push(util.template(templateName, {
VARIABLE_NAME: variableName.name,
VARIABLE_NAME: variableName,
MODULE_NAME: node.source.raw,
KEY: specifier.id
}));
};
CommonJSModuleFormatter.prototype.export = function (node, nodes) {
CommonJSFormatter.prototype.export = function (node, nodes) {
var declar = node.declaration;
if (node.default) {
@@ -68,20 +64,21 @@ CommonJSModuleFormatter.prototype.export = function (node, nodes) {
}
};
CommonJSModuleFormatter.prototype.exportSpecifier = function (specifier, node, nodes) {
var variableName = getSpecifierName(specifier);
CommonJSFormatter.prototype.exportSpecifier = function (specifier, node, nodes) {
var variableName = util.getSpecifierName(specifier);
if (node.source) {
var object = b.callExpression(b.identifier("require"), [node.source]);
if (specifier.type === "ExportBatchSpecifier") {
// export * from "foo";
nodes.push(util.template("exports-wildcard", {
MODULE_NAME: node.source.raw
OBJECT: object
}, true));
} else {
// export { foo } from "test";
nodes.push(util.template("exports-require-assign-key", {
nodes.push(util.template("exports-assign-key", {
VARIABLE_NAME: variableName.name,
MODULE_NAME: node.source.raw,
OBJECT: object,
KEY: specifier.id
}, true));
}

View File

@@ -1 +0,0 @@
[].concat(ARGUMENT);

View File

@@ -0,0 +1 @@
exports.VARIABLE_NAME = OBJECT.KEY;

View File

@@ -1 +0,0 @@
exports.VARIABLE_NAME = require(MODULE_NAME).KEY;

View File

@@ -2,4 +2,4 @@
for (var i in obj) {
exports[i] = obj[i];
}
}(require(MODULE_NAME)));
})(OBJECT);

View File

@@ -99,12 +99,14 @@ transform.transformers = {
_aliasFunctions: require("./transformers/_alias-functions"),
_blockHoist: require("./transformers/_block-hoist"),
_declarations: require("./transformers/_declarations"),
_moduleFormatter: require("./transformers/_module-formatter"),
useStrict: require("./transformers/use-strict")
};
transform.moduleFormatters = {
common: require("./modules/common")
common: require("./modules/common"),
amd: require("./modules/amd")
};
_.each(transform.transformers, function (transformer, key) {

View File

@@ -61,10 +61,6 @@ Transformer.prototype.transform = function (file) {
if (transformer.ast && transformer.ast.exit) {
transformer.ast.exit(ast, file);
}
if (file.moduleFormatter.transform) {
file.moduleFormatter.transform(ast);
}
};
Transformer.prototype.canRun = function (file) {

View File

@@ -0,0 +1,11 @@
var transform = require("../transform");
exports.ast = {
exit: function (ast, file) {
if (!transform.transformers.modules.canRun(file)) return;
if (file.moduleFormatter.transform) {
file.moduleFormatter.transform(ast);
}
}
};

View File

@@ -25,6 +25,10 @@ exports.list = function (val) {
return val ? val.split(",") : [];
};
exports.getSpecifierName = function (specifier) {
return specifier.name || specifier.id;
};
exports.ensureExpressionType = function (node) {
node.type = {
FunctionDeclaration: "FunctionExpression",

View File

@@ -47,7 +47,8 @@
"chokidar": "^0.9.0",
"source-map-support": "^0.2.7",
"esutils": "^1.1.4",
"acorn": "^0.9.0"
"acorn": "^0.9.0",
"ast-types": "^0.5.3"
},
"devDependencies": {
"es6-transpiler": "0.7.17",

View File

@@ -0,0 +1,8 @@
export default 42;
export default {};
export default [];
export default foo;
export default function () {}
export default class {}
export default function foo () {}
export default class foo {}

View File

@@ -0,0 +1,25 @@
"use strict";
define([], function () {
var exports = {};
exports.default = 42;
exports.default = {};
exports.default = [];
exports.default = foo;
exports.default = function() {};
exports.default = function() {
var _class = function() {};
return _class;
}();
exports.default = function foo() {};
exports.default = function() {
var foo = function foo() {};
return foo;
}();
return exports;
});

View File

@@ -0,0 +1,6 @@
export * from "foo";
export {foo} from "foo";
export {foo, bar} from "foo";
export {foo as bar} from "foo";
export {foo as default} from "foo";
export {foo as default, bar} from "foo";

View File

@@ -0,0 +1,21 @@
"use strict";
define(["foo"], function (_foo) {
var exports = {};
(function(obj) {
for (var i in obj) {
exports[i] = obj[i];
}
})(_foo);
exports.foo = _foo.foo;
exports.foo = _foo.foo;
exports.bar = _foo.bar;
exports.bar = _foo.foo;
exports.default = _foo.foo;
exports.default = _foo.foo;
exports.bar = _foo.bar;
return exports;
});

View File

@@ -0,0 +1,5 @@
export {foo};
export {foo, bar};
export {foo as bar};
export {foo as default};
export {foo as default, bar};

View File

@@ -0,0 +1,15 @@
"use strict";
define([], function () {
var exports = {};
exports.foo = foo;
exports.foo = foo;
exports.bar = bar;
exports.bar = foo;
exports.default = foo;
exports.default = foo;
exports.bar = bar;
return exports;
});

View File

@@ -0,0 +1,8 @@
export var foo = 1;
export var foo2 = function () {};
export var foo3;
export let foo4 = 2;
export let foo5;
export const foo6 = 3;
export function foo7 () {}
export class foo8 {}

View File

@@ -0,0 +1,29 @@
"use strict";
define([], function () {
var exports = {};
exports.foo7 = foo7;
var foo = 1;
exports.foo = foo;
var foo2 = function() {};
exports.foo2 = foo2;
var foo3;
exports.foo3 = foo3;
var _foo4 = 2;
exports.foo4 = _foo4;
var _foo5;
exports.foo5 = _foo5;
var _foo6 = 3;
exports.foo6 = _foo6;
function foo7() {}
var foo8 = function() {
var foo8 = function foo8() {};
return foo8;
}();
exports.foo8 = foo8;
return exports;
});

View File

@@ -0,0 +1,11 @@
import { isEven } from "./evens";
export function nextOdd(n) {
return isEven(n) ? n + 1 : n + 2;
}
export var isOdd = (function(isEven) {
return function(n) {
return !isEven(n);
};
})(isEven);

View File

@@ -0,0 +1,22 @@
"use strict";
define(["./evens"], function (_evens) {
var exports = {};
exports.nextOdd = nextOdd;
var isEven = _evens.isEven;
function nextOdd(n) {
return (isEven(n) ? n + 1 : n + 2);
}
var isOdd = function(isEven) {
return function(n) {
return !isEven(n);
};
}(isEven);
exports.isOdd = isOdd;
return exports;
});

View File

@@ -0,0 +1,2 @@
import foo from "foo";
import {default as foo} from "foo";

View File

@@ -0,0 +1,10 @@
"use strict";
define(["foo"], function (_foo) {
var exports = {};
var foo = _foo.default;
var foo = _foo.default;
return exports;
});

View File

@@ -0,0 +1 @@
import * as foo from "foo";

View File

@@ -0,0 +1,9 @@
"use strict";
define(["foo"], function (_foo) {
var exports = {};
var foo = _foo;
return exports;
});

View File

@@ -0,0 +1 @@
import foo, {baz as xyz} from "foo";

View File

@@ -0,0 +1,10 @@
"use strict";
define(["foo"], function (_foo) {
var exports = {};
var foo = _foo.default;
var xyz = _foo.baz;
return exports;
});

View File

@@ -0,0 +1,4 @@
import {bar} from "foo";
import {bar, baz} from "foo";
import {bar as baz} from "foo";
import {bar as baz, xyz} from "foo";

View File

@@ -0,0 +1,14 @@
"use strict";
define(["foo"], function (_foo) {
var exports = {};
var bar = _foo.bar;
var bar = _foo.bar;
var baz = _foo.baz;
var baz = _foo.bar;
var baz = _foo.bar;
var xyz = _foo.xyz;
return exports;
});

View File

@@ -0,0 +1,3 @@
import "foo";
import "foo-bar";
import "./directory/foo-bar";

View File

@@ -0,0 +1,7 @@
"use strict";
define(["foo", "foo-bar", "./directory/foo-bar"], function (_foo, _fooBar, _directoryFooBar) {
var exports = {};
return exports;
});

View File

@@ -0,0 +1,12 @@
import "foo";
import "foo-bar";
import "./directory/foo-bar";
import foo from "foo";
import * as foo from "foo";
import {bar} from "foo";
import {foo as bar} from "foo";
export {test};
export var test = 5;
export default test;

View File

@@ -0,0 +1,16 @@
"use strict";
define(["foo", "foo-bar", "./directory/foo-bar"], function (_foo, _fooBar, _directoryFooBar) {
var exports = {};
var foo = _foo.default;
var foo = _foo;
var bar = _foo.bar;
var bar = _foo.foo;
exports.test = test;
var test = 5;
exports.test = test;
exports.default = test;
return exports;
});