diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..1ec1508 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,4 @@ +# 4 space indentation +[*.js] +indent_style = space +indent_size = 2 \ No newline at end of file diff --git a/lib/ember-migrator.js b/lib/ember-migrator.js index 0b90897..8a50037 100644 --- a/lib/ember-migrator.js +++ b/lib/ember-migrator.js @@ -48,11 +48,7 @@ function EmberMigrator(options){ // Map from class name to export path in ember-cli // E.g., App.MyClassView -> /app/views/my-class.js // Also, window.App -> app/app.js - // We handle the difference between main app space and window simply with isWindowVar flag this.classesFilepathMap = Object.create(null); - // Some things are stored on the window directly, e.g., the main application - // E.g., window.App -> /app/app.js - this.windowFilepathMap = Object.create(null); this.ui = new UI({ inputStream: process.stdin, outputStream: process.stdout @@ -193,7 +189,7 @@ EmberMigrator.prototype.writeLine = function(message){ if (!this.testing) { return this.ui.writeLine.apply(this.ui, arguments); } -} +}; EmberMigrator.prototype.splitFile = function(filePath) { var file = fs.readFileSync(path.join(this.inputDirectory, filePath)).toString(); @@ -217,7 +213,7 @@ EmberMigrator.prototype.splitFile = function(filePath) { var firstNodeComments = ast.program.comments; var that = this; - var addTypedNode = function(node, filePath, className, isWindow) { + var addTypedNode = function(node, filePath, className) { var newType = TypedExport.determineType(filePath, className); var fileName = TypedExport.filePathForClassname(className, newType, filePath, that.splitFiles); @@ -233,11 +229,13 @@ EmberMigrator.prototype.splitFile = function(filePath) { appName: that.appName }); that.splitFiles[fileName] = typedExport; - // Every typed export needs to be able to be looked up on this map - that.classesFilepathMap[typedExport.exportName] = { - moduleName: typedExport.exportPath(that.appName), - isWindow: isWindow - }; + if (typedExport.exportName) { + // Every module we export needs to be looked up on this map for imports + that.classesFilepathMap[typedExport.exportName] = { + moduleName: typedExport.exportPath(that.appName) + }; + } + // Keep track of all exports so far typedExports.push(typedExport); } that.splitFiles[fileName].astNodes.push(node); @@ -301,14 +299,14 @@ EmberMigrator.prototype.splitFile = function(filePath) { flattenedNodes.forEach(function(flatNode) { // We know we are an assignment var expression = flatNode.expression; + // Special case app definition to export, all other window exports + // should not be handled this way if (namedTypes.MemberExpression.check(expression.left) && (expression.left.object.name === this.rootAppName || - expression.left.object.name === "window")) { + (expression.left.object.name === "window" && expression.left.property.name === this.rootAppName))) { - // See if we are assigning the class on the App or window - var isWindow = expression.left.object.name === "window"; className = expression.left.property.name; - addTypedNode(flatNode, filePath, className, isWindow); + addTypedNode(flatNode, filePath, className); isNodeStored = true; } }.bind(this)); @@ -319,7 +317,7 @@ EmberMigrator.prototype.splitFile = function(filePath) { node.expression.left.object.name === 'module' && node.expression.left.property.name === 'exports') { if(namedTypes.Identifier.check(node.expression.right)){ - addTypedNode(node, filePath, node.expression.right.name, false); + addTypedNode(node, filePath, node.expression.right.name); isNodeStored = true; } } @@ -384,17 +382,8 @@ EmberMigrator.prototype.convertFile = function(typedExport){ // for some reason there is a rogue semicolon code = code.replace(/\n;\n/, '\n'); - code = code.replace(new RegExp(this.rootAppName + "\\.", 'g'), ''); code = code.replace(/Em\./g, 'Ember.'); - // For any module imported that used to be a window global - Object.keys(this.classesFilepathMap).forEach(function(name) { - var module = this.classesFilepathMap[name]; - if (module.isWindow) { - code = code.replace("window." + name, name); - } - }, this); - code = code + "\n" + "export default " + typedExport.exportName + ";\n"; return code; @@ -410,9 +399,4 @@ EmberMigrator.prototype.flushConvertedFiles = function(splitFiles){ }, this); }; - -function capitalize(string){ - return string.charAt(0).toUpperCase() + string.slice(1); -} - module.exports = EmberMigrator; diff --git a/lib/migrator-visitor.js b/lib/migrator-visitor.js index dab36d2..cf8663b 100644 --- a/lib/migrator-visitor.js +++ b/lib/migrator-visitor.js @@ -69,7 +69,7 @@ var MigratorVisitorPrototype = { var rightNode = node.value.right; if (namedTypes.MemberExpression.check(node.value.left) && (leftNode.object.name === this.rootAppName || - leftNode.object.name === 'window') ){ + (leftNode.object.name === "window" && leftNode.property.name === this.rootAppName))) { this._exportName = leftNode.property.name; var newNode = builders.variableDeclaration("var", [builders.variableDeclarator(builders.identifier(leftNode.property.name), rightNode)]); // Recursively check this node to see if it is a member expression and we need an import @@ -124,7 +124,7 @@ var MigratorVisitorPrototype = { oldFileName: requirePath, appName: this.localAppName, outputDirectory: this.outputDirectory - }) + }); var exportPath = instance.exportPath(this.rootAppName); @@ -136,6 +136,10 @@ var MigratorVisitorPrototype = { } }; +function isAppDefinition(leftNode, appName) { + return leftNode.object.name === "window" && leftNode.property.name === appName; +} + MigratorVisitor.prototype = Object.create(MigratorVisitorPrototype); MigratorVisitor.prototype.visit = function(ast) { diff --git a/lib/typed-export.js b/lib/typed-export.js index db10e29..090b71e 100644 --- a/lib/typed-export.js +++ b/lib/typed-export.js @@ -33,7 +33,7 @@ TypedExport.knownTypes = [ TypedExport.pluralizeType = function(type) { return type + 's'; -} +}; TypedExport.determineType = function(filePath, className) { // First check to see if any class matches @@ -60,7 +60,7 @@ TypedExport.determineType = function(filePath, className) { }, this); } return type; -} +}; // TODO(Tony) handle path and name TypedExport.prototype.exportPath = function() { @@ -89,11 +89,17 @@ TypedExport.convertToOutputFilename = function(stringInput) { filename.push(c); }); return filename.join('').toLowerCase(); -} +}; TypedExport.filePathForClassname = function(className, type, filePath, exportFiles) { var newFilePath; - if (type === 'unknown') { + + if (!className && filePath !== 'application.js') { + // className = null means we are not exporting anything for this filePath + // so we should send it to special globals folder + newFilePath = path.join('globals', filePath); + } + else if (type === 'unknown') { newFilePath = filePath; } else { var filename = TypedExport.convertToOutputFilename(className); @@ -138,6 +144,6 @@ TypedExport.filePathForClassname = function(className, type, filePath, exportFil } } return newFilePath; -} +}; module.exports = TypedExport; diff --git a/test/fixtures/vanilla/input/analytics/global_analytics.js b/test/fixtures/vanilla/input/analytics/global_analytics.js new file mode 100644 index 0000000..c1d3c2e --- /dev/null +++ b/test/fixtures/vanilla/input/analytics/global_analytics.js @@ -0,0 +1,3 @@ +(function () { + window.global_analytics = 'inject thorough analytics solution'; +})(); \ No newline at end of file diff --git a/test/fixtures/vanilla/input/window_var.js b/test/fixtures/vanilla/input/window_var.js new file mode 100644 index 0000000..1ec2f95 --- /dev/null +++ b/test/fixtures/vanilla/input/window_var.js @@ -0,0 +1,3 @@ +window.vip_global = function () { + console.log('the coolest'); +}; \ No newline at end of file diff --git a/test/fixtures/vanilla/output/globals/analytics/global-analytics.js b/test/fixtures/vanilla/output/globals/analytics/global-analytics.js new file mode 100644 index 0000000..052fb1e --- /dev/null +++ b/test/fixtures/vanilla/output/globals/analytics/global-analytics.js @@ -0,0 +1,5 @@ +(function () { + window.global_analytics = 'inject thorough analytics solution'; +})(); + +export default undefined; diff --git a/test/fixtures/vanilla/output/globals/window-var.js b/test/fixtures/vanilla/output/globals/window-var.js new file mode 100644 index 0000000..f2f3106 --- /dev/null +++ b/test/fixtures/vanilla/output/globals/window-var.js @@ -0,0 +1,5 @@ +window.vip_global = function () { + console.log('the coolest'); +}; + +export default undefined; diff --git a/test/models-test.js b/test/models-test.js index 32b0637..a32eb83 100644 --- a/test/models-test.js +++ b/test/models-test.js @@ -141,4 +141,12 @@ describe('migrating models', function(){ it(migrates('controllers/with-mixin.js')); }); + describe('Moves window var definition into globals directory', function(){ + it(migrates('globals/window-var.js')); + }); + + describe('Moves self executing anonymous functions to globals', function(){ + it(migrates('globals/analytics/global-analytics.js')); + }); + }); diff --git a/test/test_helper.js b/test/test_helper.js index b6fea31..093604d 100644 --- a/test/test_helper.js +++ b/test/test_helper.js @@ -22,13 +22,13 @@ function migrator(options) { migrator.expectedOutputFixtureDirectory = path.join(__dirname, "fixtures/", opts.inputFixtures, '/output'); migrator.clean = function(){ rimraf.sync(tmpDir); - } + }; return migrator; } function migratorResult(migrator, fixtureName){ var file = path.join(migrator.outputDirectory, fixtureName); - return fs.readFileSync(file).toString().split('\n');; + return fs.readFileSync(file).toString().split('\n'); } function fixture(migrator, fixtureName){ @@ -57,7 +57,7 @@ module.exports.it = function(result){ return it(result, arguments[1]); } return it(result[0], result[1]); -} +}; module.exports.it.only = function(result){ if (!Array.isArray(result)) {