module.exports = File;
var SHEBANG_REGEX = /^\#\!.*/;
var transform = require("./transform");
var recast = require("recast");
var util = require("./util");
var b = require("recast").types.builders;
var _ = require("lodash");
function File(opts) {
this.declarations = {};
this.uids = {};
this.opts = File.normaliseOptions(opts);
this.ast = {};
}
File.normaliseOptions = function (opts) {
opts = opts || {};
_.defaults(opts, {
blacklist: [],
whitelist: [],
sourceMap: false,
filename: "unknown",
format: {}
});
_.defaults(opts, {
sourceFileName: opts.filename,
sourceMapName: opts.filename
});
transform._ensureTransformerNames("blacklist", opts.blacklist);
transform._ensureTransformerNames("whitelist", opts.whitelist);
return opts;
};
File.prototype.parseShebang = function (code) {
var shebangMatch = code.match(SHEBANG_REGEX);
Iif (shebangMatch) {
this.shebang = shebangMatch[0];
// remove shebang
code = code.replace(SHEBANG_REGEX, "");
}
return code;
};
File.prototype.addDeclaration = function (name) {
var declar = this.declarations[name];
if (declar) return declar.uid;
var uid = b.identifier(this.generateUid(name));
this.declarations[name] = {
uid: uid,
node: util.template(name)
};
return uid;
};
File.prototype.parse = function (code) {
var self = this;
code = this.parseShebang(code);
return util.parse(this.opts, code, function (tree) {
return self.transform(tree);
});
};
File.prototype.transform = function (ast) {
this.ast = ast;
var self = this;
_.each(transform.transformers, function (transformer) {
transformer.transform(self);
});
var body = ast.program.body;
_.each(this.declarations, function (declar) {
body.unshift(b.variableDeclaration("var", [
b.variableDeclarator(declar.uid, declar.node)
]));
});
return this.generate();
};
File.prototype.generate = function () {
var opts = this.opts;
var ast = this.ast;
var printOpts = {};
if (opts.sourceMap) {
printOpts.sourceMapName = opts.sourceMapName;
}
var result = recast.print(ast, printOpts);
var code = result.code;
Iif (this.shebang) {
// add back shebang
code = this.shebang + code;
}
if (opts.sourceMap === "inline") {
code += "\n" + util.sourceMapToComment(result.map);
}
return {
code: code,
map: result.map || null,
ast: ast
};
};
File.prototype.generateUid = function (name) {
var uids = this.uids;
var i = uids[name] || 1;
var id = name;
if (i > 1) id += i;
uids[name] = i + 1;
return "_" + id;
};
|