Created
September 3, 2015 16:01
-
-
Save tschneidereit/7e2eee4f6870d00dfb78 to your computer and use it in GitHub Desktop.
TypeScript module merger
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var esprima = require('esprima'); | |
var codegen = require('escodegen'); | |
var fs = require('fs'); | |
function optimizeFile(path) { | |
console.error("Optimizing file", path); | |
fs.readFile(path, function (err, data) { | |
if (err) { | |
throw err; | |
} | |
var ast = esprima.parse(data, { raw: true, tokens: true, range: true, comment: true }); | |
ast = codegen.attachComments(ast, ast.comments, ast.tokens); | |
console.error("Merged " + optimizeModules(ast.body, 0, 0) + " module bodies."); | |
fs.writeFile(path, codegen.generate(ast, {comment: true})); | |
// console.log(codegen.generate(ast, {comment: true})); | |
}); | |
} | |
process.argv.slice(2).forEach(function(path) { | |
optimizeFile(path); | |
}); | |
function tabs(nesting) { | |
return ' '.substr(0, nesting * 2); | |
} | |
function optimizeModules(nodes, nesting, mergeCount) { | |
var moduleName = null; | |
var bodies = []; | |
console.error(tabs(nesting) + "Optimizing " + nodes.length); | |
for (var i = 0; i < nodes.length - 1; i++) { | |
var name = getModuleName(nodes[i]); | |
var module = getModuleDeclaration(name, nodes[i + 1]); | |
if (!name || !module) { | |
if (bodies.length) { | |
mergeCount = mergeBodies(moduleName, bodies, nodes, nesting, mergeCount); | |
i -= bodies.length * 2 - 2; | |
moduleName = null; | |
bodies = []; | |
} | |
continue; | |
} | |
if (name !== moduleName) { | |
if (bodies.length) { | |
mergeCount = mergeBodies(moduleName, bodies, nodes, nesting, mergeCount); | |
i -= bodies.length * 2 - 2; | |
} | |
moduleName = name; | |
bodies = []; | |
console.error(tabs(nesting) + "Module " + moduleName + ' found at ' + i); | |
} | |
bodies.push({name: nodes[i], body: module}); | |
i++; | |
} | |
if (bodies && bodies.length) | |
mergeCount = mergeBodies(moduleName, bodies, nodes, nesting, mergeCount); | |
return mergeCount; | |
} | |
function mergeBodies(name, bodies, parentNodeList, nesting, mergeCount) { | |
mergeCount += bodies.length - 1; | |
var result = bodies[0].body; | |
console.error(tabs(nesting) + 'Merging ' + name + ': ' + bodies.length + ' / ' + parentNodeList.length); | |
for (var i = 1; i < bodies.length; i++) { | |
var entry = bodies[i]; | |
// console.error(tabs(nesting) + "merging " + name + ' at ' + entry.index, entry.index - context.offset); | |
result.push.apply(result, entry.body); | |
parentNodeList.splice(parentNodeList.indexOf(entry.name), 2); | |
} | |
return optimizeModules(result, nesting + 1, mergeCount); | |
} | |
function getModuleName(node) { | |
if (node.type !== 'VariableDeclaration' || node.declarations.length !== 1) | |
return null; | |
var declaration = node.declarations[0]; | |
if (declaration.type !== 'VariableDeclarator' || declaration.init !== null) | |
return null; | |
return declaration.id.name; | |
} | |
function getModuleDeclaration(name, node) { | |
if (node.type !== 'ExpressionStatement') | |
return null; | |
var expression = node.expression; | |
if (expression.type !== 'CallExpression') | |
return null; | |
var callee = expression.callee; | |
if (callee.type !== 'FunctionExpression' || callee.id !== null || | |
callee.params.length !== 1 || callee.params[0].name !== name) | |
{ | |
return null; | |
} | |
var args = expression.arguments; | |
if (args.length !== 1 || args[0].type !== 'LogicalExpression' && args[0].type !== 'AssignmentExpression' || | |
args[0].left.name.indexOf(name) === -1) | |
{ | |
return null; | |
} | |
return callee.body.body; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment