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",