From ef070c28189bc369ef761a4189287200231b84e0 Mon Sep 17 00:00:00 2001 From: ijlee2 Date: Sun, 26 Apr 2020 10:04:51 -0500 Subject: [PATCH 01/23] Renamed the folder to classic-to-flat --- test/fixtures/{classic-app => classic-to-flat}/input.js | 0 test/fixtures/{classic-app => classic-to-flat}/output.js | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename test/fixtures/{classic-app => classic-to-flat}/input.js (100%) rename test/fixtures/{classic-app => classic-to-flat}/output.js (100%) diff --git a/test/fixtures/classic-app/input.js b/test/fixtures/classic-to-flat/input.js similarity index 100% rename from test/fixtures/classic-app/input.js rename to test/fixtures/classic-to-flat/input.js diff --git a/test/fixtures/classic-app/output.js b/test/fixtures/classic-to-flat/output.js similarity index 100% rename from test/fixtures/classic-app/output.js rename to test/fixtures/classic-to-flat/output.js From 79b0eafc505c81fb5644ab56c8f66f56a0224ff5 Mon Sep 17 00:00:00 2001 From: ijlee2 Date: Sun, 26 Apr 2020 10:29:18 -0500 Subject: [PATCH 02/23] Added test examples of a "typical" nested component and a template-only component --- test/fixtures/classic-to-flat/input.js | 54 +++++++++++++++++++++---- test/fixtures/classic-to-flat/output.js | 44 +++++++++++++++++--- 2 files changed, 85 insertions(+), 13 deletions(-) diff --git a/test/fixtures/classic-to-flat/input.js b/test/fixtures/classic-to-flat/input.js index 37e8058..14b6d93 100644 --- a/test/fixtures/classic-to-flat/input.js +++ b/test/fixtures/classic-to-flat/input.js @@ -1,38 +1,78 @@ module.exports = { app: { 'app.js': '// app', + components: { + // A standalone component 'top-level-component.js': '// top-level-component.js', + + // A nested component + 'parent-component.js': '// parent-component.js', + 'parent-component': { + 'child-component.js': '// parent-component/child-component.js', + 'child-component': { + 'grandchild-component.js': '// parent-component/child-component/grandchild-component.js' + } + }, + + // Another nested component nested1: { 'nested-component.js': '// nested1/nested-component.js', nested2: { - 'super-nested-component.js': '// nested1/nested2/super-nested-component.js', + 'super-nested-component.js': '// nested1/nested2/super-nested-component.js' } }, + + // A component with layoutName 'layout-name': { - 'has-layout-name.js': `// top-level-component.js - Component.extend({ layoutName: "components/layout-name/layout-name-template" });`, + 'has-layout-name.js': [ + '// top-level-component.js', + 'Component.extend({ layoutName: "components/layout-name/layout-name-template" });' + ].join('\n') } }, + templates: { 'application.hbs': '{{outlet}}', + components: { + // A standalone component 'top-level-component.hbs': '{{!-- top-level-component.hbs --}}', + + // A template-only component + 'template-only-component.hbs': '{{!-- template-only-component.hbs --}}', + + // A nested component + 'parent-component.hbs': '{{!-- parent-component.hbs --}}', + 'parent-component': { + 'child-component.hbs': '{{!-- parent-component/child-component.hbs --}}', + 'child-component': { + 'grandchild-component.hbs': '{{!-- parent-component/child-component/grandchild-component.hbs --}}' + } + }, + + // Another nested component nested1: { 'nested-component.hbs': '{{!-- nested1/nested-component.hbs --}}', nested2: { 'super-nested-component.hbs': '{{!-- nested1/nested2/super-nested-component.hbs --}}' } }, + + // A component with layoutName 'layout-name': { - 'layout-name-template.hbs': '{{!-- layout-name-template.hbs --}}', + 'layout-name-template.hbs': '{{!-- layout-name-template.hbs --}}' }, + + // A partial template 'partials': { 'partials-template.hbs': '{{!-- partials-template.hbs --}}', - 'with-partial.hbs': `{{!-- with-partial.hbs --}} - {{partial 'components/partials/partials-template'}}`, + 'with-partial.hbs': [ + '{{!-- with-partial.hbs --}}', + '{{partial "components/partials/partials-template"}}' + ].join('\n') } } } - }, + } }; \ No newline at end of file diff --git a/test/fixtures/classic-to-flat/output.js b/test/fixtures/classic-to-flat/output.js index 038f942..97aa7f7 100644 --- a/test/fixtures/classic-to-flat/output.js +++ b/test/fixtures/classic-to-flat/output.js @@ -1,9 +1,28 @@ module.exports = { app: { 'app.js': '// app', + components: { + // A standalone component 'top-level-component.hbs': '{{!-- top-level-component.hbs --}}', 'top-level-component.js': '// top-level-component.js', + + // A template-only component + 'template-only-component.hbs': '{{!-- template-only-component.hbs --}}', + + // A nested component + 'parent-component.hbs': '{{!-- parent-component.hbs --}}', + 'parent-component.js': '// parent-component.js', + 'parent-component': { + 'child-component.hbs': '{{!-- parent-component/child-component.hbs --}}', + 'child-component.js': '// parent-component/child-component.js', + 'child-component': { + 'grandchild-component.hbs': '{{!-- parent-component/child-component/grandchild-component.hbs --}}', + 'grandchild-component.js': '// parent-component/child-component/grandchild-component.js' + } + }, + + // Another nested component nested1: { 'nested-component.hbs': '{{!-- nested1/nested-component.hbs --}}', 'nested-component.js': '// nested1/nested-component.js', @@ -12,23 +31,36 @@ module.exports = { 'super-nested-component.js': '// nested1/nested2/super-nested-component.js' } }, + + // A component with layoutName 'layout-name': { - 'has-layout-name.js': `// top-level-component.js - Component.extend({ layoutName: "components/layout-name/layout-name-template" });`, + 'has-layout-name.js': [ + '// top-level-component.js', + 'Component.extend({ layoutName: "components/layout-name/layout-name-template" });' + ].join('\n') }, + + // A component with partial 'partials': { - 'with-partial.hbs': `{{!-- with-partial.hbs --}} - {{partial 'components/partials/partials-template'}}`, + 'with-partial.hbs': [ + '{{!-- with-partial.hbs --}}', + '{{partial "components/partials/partials-template"}}' + ].join('\n') } }, + templates: { 'application.hbs': '{{outlet}}', + components: { + // A component with layoutName 'layout-name': { - 'layout-name-template.hbs': '{{!-- layout-name-template.hbs --}}', + 'layout-name-template.hbs': '{{!-- layout-name-template.hbs --}}' }, + + // A partial template 'partials': { - 'partials-template.hbs': '{{!-- partials-template.hbs --}}' + 'partials-template.hbs': '{{!-- partials-template.hbs --}}', } } } From 590a2b1754fad5c5b69974bdb0f4dbc4ff8ab2b8 Mon Sep 17 00:00:00 2001 From: ijlee2 Date: Sun, 26 Apr 2020 16:48:13 -0500 Subject: [PATCH 03/23] Stored projectRoot as a class field --- lib/migrator.js | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/lib/migrator.js b/lib/migrator.js index ee3744a..261d46d 100644 --- a/lib/migrator.js +++ b/lib/migrator.js @@ -6,30 +6,32 @@ const { moveFile, removeDirs } = require('./utils/file') module.exports = class Migrator { constructor(options) { - this.options = options; + const { projectRoot } = options; + + this.projectRoot = projectRoot; } async execute() { - let sourceComponentTemplatesPath = path.join(this.options.projectRoot, 'app/templates/components'); + let sourceComponentTemplatesPath = path.join(this.projectRoot, 'app/templates/components'); var sourceComponentTemplateFilePaths = glob.sync(`${sourceComponentTemplatesPath}/**/*.hbs`); - let sourceComponentPath = path.join(this.options.projectRoot, 'app/components'); + let sourceComponentPath = path.join(this.projectRoot, 'app/components'); let sourceComponentFilePaths = glob.sync(`${sourceComponentPath}/**/*.js`); let templatesWithLayoutName = getLayoutNameTemplates(sourceComponentFilePaths); if (templatesWithLayoutName.length) { sourceComponentTemplateFilePaths = sourceComponentTemplateFilePaths.filter(sourceTemplateFilePath => { - let sourceTemplatePathInApp = sourceTemplateFilePath.slice(this.options.projectRoot.length); // '/app/templates/components/nested1/nested-component.hbs' + let sourceTemplatePathInApp = sourceTemplateFilePath.slice(this.projectRoot.length); // '/app/templates/components/nested1/nested-component.hbs' let templatePath = sourceTemplatePathInApp.slice('app/templates/'.length); // '/nested1/nested-component.hbs' return !templatesWithLayoutName.includes(templatePath.slice(1).replace('.hbs', '')); }); } - let sourceTemplatesPath = path.join(this.options.projectRoot, 'app/templates'); + let sourceTemplatesPath = path.join(this.projectRoot, 'app/templates'); var sourceTemplateFilePaths = glob.sync(`${sourceTemplatesPath}/**/*.hbs`); let templatesInPartials = getPartialTemplates(sourceTemplateFilePaths); if (templatesInPartials.length) { sourceComponentTemplateFilePaths = sourceComponentTemplateFilePaths.filter(sourceTemplateFilePath => { - let sourceTemplatePathInApp = sourceTemplateFilePath.slice(this.options.projectRoot.length); // '/app/templates/components/nested1/nested-component.hbs' + let sourceTemplatePathInApp = sourceTemplateFilePath.slice(this.projectRoot.length); // '/app/templates/components/nested1/nested-component.hbs' if (/\/\-[\w\-]+\.hbs/.test(sourceTemplatePathInApp)) { sourceTemplatePathInApp = sourceTemplatePathInApp.replace('/-', '/'); } @@ -39,9 +41,9 @@ module.exports = class Migrator { } sourceComponentTemplateFilePaths.forEach(sourceTemplateFilePath => { - let sourceTemplatePathInApp = sourceTemplateFilePath.slice(this.options.projectRoot.length); // '/app/templates/components/nested1/nested-component.hbs' + let sourceTemplatePathInApp = sourceTemplateFilePath.slice(this.projectRoot.length); // '/app/templates/components/nested1/nested-component.hbs' let templatePath = sourceTemplatePathInApp.slice('app/templates/components/'.length); // '/nested1/nested-component.hbs' - let targetTemplateFilePath = path.join(this.options.projectRoot, 'app/components', templatePath); // '[APP_PATH]/app/components/nested1/nested-component.hbs' + let targetTemplateFilePath = path.join(this.projectRoot, 'app/components', templatePath); // '[APP_PATH]/app/components/nested1/nested-component.hbs' moveFile(sourceTemplateFilePath, targetTemplateFilePath); }); From 9b6be57747616b905699de71d1e7c3b53c5c4ddd Mon Sep 17 00:00:00 2001 From: ijlee2 Date: Sun, 26 Apr 2020 16:48:54 -0500 Subject: [PATCH 04/23] Refactored migrator by creating findClassicComponentTemplates and removeEmptyClassicComponentDirectories methods --- lib/migrator.js | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/lib/migrator.js b/lib/migrator.js index 261d46d..e60d698 100644 --- a/lib/migrator.js +++ b/lib/migrator.js @@ -11,9 +11,21 @@ module.exports = class Migrator { this.projectRoot = projectRoot; } + findClassicComponentTemplates() { + const templateFolderPath = path.join(this.projectRoot, 'app/templates/components'); + const templateFilePaths = glob.sync(`${templateFolderPath}/**/*.hbs`); + + return templateFilePaths; + } + + async removeEmptyClassicComponentDirectories(removeOnlyEmptyDirectories) { + const templateFolderPath = path.join(this.projectRoot, 'app/templates/components'); + + await removeDirs(templateFolderPath, removeOnlyEmptyDirectories); + } + async execute() { - let sourceComponentTemplatesPath = path.join(this.projectRoot, 'app/templates/components'); - var sourceComponentTemplateFilePaths = glob.sync(`${sourceComponentTemplatesPath}/**/*.hbs`); + let sourceComponentTemplateFilePaths = this.findClassicComponentTemplates(); let sourceComponentPath = path.join(this.projectRoot, 'app/components'); let sourceComponentFilePaths = glob.sync(`${sourceComponentPath}/**/*.js`); @@ -54,7 +66,7 @@ module.exports = class Migrator { console.info(`❌ Did not move '${template}' due to usage as a "partial"`); }); - let onlyRemoveEmptyDirs = Boolean(templatesWithLayoutName.length); - await removeDirs(sourceComponentTemplatesPath, onlyRemoveEmptyDirs); + const removeOnlyEmptyDirectories = Boolean(templatesWithLayoutName.length); + await this.removeEmptyClassicComponentDirectories(removeOnlyEmptyDirectories); } } \ No newline at end of file From ed9725cb0cca4c565ea372f861e492ea207db2c2 Mon Sep 17 00:00:00 2001 From: ijlee2 Date: Sun, 26 Apr 2020 16:50:08 -0500 Subject: [PATCH 05/23] Refactored migrator by creating findClassicComponentClasses method --- lib/migrator.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/migrator.js b/lib/migrator.js index e60d698..502a333 100644 --- a/lib/migrator.js +++ b/lib/migrator.js @@ -18,6 +18,13 @@ module.exports = class Migrator { return templateFilePaths; } + findClassicComponentClasses() { + const classFolderPath = path.join(this.projectRoot, 'app/components'); + const classFilePaths = glob.sync(`${classFolderPath}/**/*.js`); + + return classFilePaths; + } + async removeEmptyClassicComponentDirectories(removeOnlyEmptyDirectories) { const templateFolderPath = path.join(this.projectRoot, 'app/templates/components'); @@ -26,9 +33,8 @@ module.exports = class Migrator { async execute() { let sourceComponentTemplateFilePaths = this.findClassicComponentTemplates(); + let sourceComponentFilePaths = this.findClassicComponentClasses(); - let sourceComponentPath = path.join(this.projectRoot, 'app/components'); - let sourceComponentFilePaths = glob.sync(`${sourceComponentPath}/**/*.js`); let templatesWithLayoutName = getLayoutNameTemplates(sourceComponentFilePaths); if (templatesWithLayoutName.length) { sourceComponentTemplateFilePaths = sourceComponentTemplateFilePaths.filter(sourceTemplateFilePath => { From a689def6b7c9278637ecd88d18d04edab6736848 Mon Sep 17 00:00:00 2001 From: ijlee2 Date: Sun, 26 Apr 2020 16:50:31 -0500 Subject: [PATCH 06/23] Shortened variable names for readability --- lib/migrator.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/migrator.js b/lib/migrator.js index 502a333..03b8d3a 100644 --- a/lib/migrator.js +++ b/lib/migrator.js @@ -32,12 +32,12 @@ module.exports = class Migrator { } async execute() { - let sourceComponentTemplateFilePaths = this.findClassicComponentTemplates(); - let sourceComponentFilePaths = this.findClassicComponentClasses(); + let templateFilePaths = this.findClassicComponentTemplates(); + let classFilePaths = this.findClassicComponentClasses(); - let templatesWithLayoutName = getLayoutNameTemplates(sourceComponentFilePaths); + let templatesWithLayoutName = getLayoutNameTemplates(classFilePaths); if (templatesWithLayoutName.length) { - sourceComponentTemplateFilePaths = sourceComponentTemplateFilePaths.filter(sourceTemplateFilePath => { + templateFilePaths = templateFilePaths.filter(sourceTemplateFilePath => { let sourceTemplatePathInApp = sourceTemplateFilePath.slice(this.projectRoot.length); // '/app/templates/components/nested1/nested-component.hbs' let templatePath = sourceTemplatePathInApp.slice('app/templates/'.length); // '/nested1/nested-component.hbs' return !templatesWithLayoutName.includes(templatePath.slice(1).replace('.hbs', '')); @@ -48,7 +48,7 @@ module.exports = class Migrator { var sourceTemplateFilePaths = glob.sync(`${sourceTemplatesPath}/**/*.hbs`); let templatesInPartials = getPartialTemplates(sourceTemplateFilePaths); if (templatesInPartials.length) { - sourceComponentTemplateFilePaths = sourceComponentTemplateFilePaths.filter(sourceTemplateFilePath => { + templateFilePaths = templateFilePaths.filter(sourceTemplateFilePath => { let sourceTemplatePathInApp = sourceTemplateFilePath.slice(this.projectRoot.length); // '/app/templates/components/nested1/nested-component.hbs' if (/\/\-[\w\-]+\.hbs/.test(sourceTemplatePathInApp)) { sourceTemplatePathInApp = sourceTemplatePathInApp.replace('/-', '/'); @@ -58,7 +58,7 @@ module.exports = class Migrator { }); } - sourceComponentTemplateFilePaths.forEach(sourceTemplateFilePath => { + templateFilePaths.forEach(sourceTemplateFilePath => { let sourceTemplatePathInApp = sourceTemplateFilePath.slice(this.projectRoot.length); // '/app/templates/components/nested1/nested-component.hbs' let templatePath = sourceTemplatePathInApp.slice('app/templates/components/'.length); // '/nested1/nested-component.hbs' let targetTemplateFilePath = path.join(this.projectRoot, 'app/components', templatePath); // '[APP_PATH]/app/components/nested1/nested-component.hbs' From e3953ff53245151be1414e39260238bff59655fe Mon Sep 17 00:00:00 2001 From: ijlee2 Date: Sun, 26 Apr 2020 16:51:39 -0500 Subject: [PATCH 07/23] Refactored migrator by creating skipTemplatesUsedAsLayoutName method --- lib/migrator.js | 42 +++++++++++++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/lib/migrator.js b/lib/migrator.js index 03b8d3a..4b946e8 100644 --- a/lib/migrator.js +++ b/lib/migrator.js @@ -25,6 +25,32 @@ module.exports = class Migrator { return classFilePaths; } + skipTemplatesUsedAsLayoutName(templateFilePaths) { + const classFilePaths = this.findClassicComponentClasses(); + const componentsWithLayoutName = getLayoutNameTemplates(classFilePaths); + + if (componentsWithLayoutName.length) { + componentsWithLayoutName.sort().forEach(component => { + console.info(`❌ Did not move '${component}' due to usage as "layoutName" in a component`); + }); + + templateFilePaths = templateFilePaths.filter(templateFilePath => { + // Extract '/app/templates/components/nested1/nested-component.hbs' + const filePathFromApp = templateFilePath.slice(this.projectRoot.length); + + // Extract '/components/nested1/nested-component.hbs' + const filePathFromAppTemplates = filePathFromApp.slice('app/templates/'.length); + + // Extract 'components/nested1/nested-component' + const classFilePath = filePathFromAppTemplates.slice(1).replace('.hbs', ''); + + return !componentsWithLayoutName.includes(classFilePath); + }); + } + + return templateFilePaths; + } + async removeEmptyClassicComponentDirectories(removeOnlyEmptyDirectories) { const templateFolderPath = path.join(this.projectRoot, 'app/templates/components'); @@ -35,14 +61,8 @@ module.exports = class Migrator { let templateFilePaths = this.findClassicComponentTemplates(); let classFilePaths = this.findClassicComponentClasses(); - let templatesWithLayoutName = getLayoutNameTemplates(classFilePaths); - if (templatesWithLayoutName.length) { - templateFilePaths = templateFilePaths.filter(sourceTemplateFilePath => { - let sourceTemplatePathInApp = sourceTemplateFilePath.slice(this.projectRoot.length); // '/app/templates/components/nested1/nested-component.hbs' - let templatePath = sourceTemplatePathInApp.slice('app/templates/'.length); // '/nested1/nested-component.hbs' - return !templatesWithLayoutName.includes(templatePath.slice(1).replace('.hbs', '')); - }); - } + templateFilePaths = this.skipTemplatesUsedAsLayoutName(templateFilePaths); + let sourceTemplatesPath = path.join(this.projectRoot, 'app/templates'); var sourceTemplateFilePaths = glob.sync(`${sourceTemplatesPath}/**/*.hbs`); @@ -65,9 +85,9 @@ module.exports = class Migrator { moveFile(sourceTemplateFilePath, targetTemplateFilePath); }); - templatesWithLayoutName.sort().forEach(template => { - console.info(`❌ Did not move '${template}' due to usage as "layoutName" in a component`); - }); + + const templatesWithLayoutName = getLayoutNameTemplates(classFilePaths); + templatesInPartials.sort().forEach(template => { console.info(`❌ Did not move '${template}' due to usage as a "partial"`); }); From e66010906bd23ce81f12c0663ef67175f5321261 Mon Sep 17 00:00:00 2001 From: ijlee2 Date: Sun, 26 Apr 2020 16:52:17 -0500 Subject: [PATCH 08/23] Refactored migrator by creating findTemplates method --- lib/migrator.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/migrator.js b/lib/migrator.js index 4b946e8..d7165dc 100644 --- a/lib/migrator.js +++ b/lib/migrator.js @@ -25,6 +25,13 @@ module.exports = class Migrator { return classFilePaths; } + findTemplates() { + const templateFolderPath = path.join(this.projectRoot, 'app/templates'); + const templateFilePaths = glob.sync(`${templateFolderPath}/**/*.hbs`); + + return templateFilePaths; + } + skipTemplatesUsedAsLayoutName(templateFilePaths) { const classFilePaths = this.findClassicComponentClasses(); const componentsWithLayoutName = getLayoutNameTemplates(classFilePaths); @@ -64,8 +71,7 @@ module.exports = class Migrator { templateFilePaths = this.skipTemplatesUsedAsLayoutName(templateFilePaths); - let sourceTemplatesPath = path.join(this.projectRoot, 'app/templates'); - var sourceTemplateFilePaths = glob.sync(`${sourceTemplatesPath}/**/*.hbs`); + let sourceTemplateFilePaths = this.findTemplates(); let templatesInPartials = getPartialTemplates(sourceTemplateFilePaths); if (templatesInPartials.length) { templateFilePaths = templateFilePaths.filter(sourceTemplateFilePath => { From 43d6225513ab07e02a08fc2b1de4b855d480866a Mon Sep 17 00:00:00 2001 From: ijlee2 Date: Sun, 26 Apr 2020 16:52:43 -0500 Subject: [PATCH 09/23] Refactored migrator by creating skipTemplatesUsedAsPartial method --- lib/migrator.js | 48 ++++++++++++++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/lib/migrator.js b/lib/migrator.js index d7165dc..23a464e 100644 --- a/lib/migrator.js +++ b/lib/migrator.js @@ -58,6 +58,35 @@ module.exports = class Migrator { return templateFilePaths; } + skipTemplatesUsedAsPartial(templateFilePaths) { + const componentsWithPartial = getPartialTemplates(this.findTemplates()); + + if (componentsWithPartial.length) { + componentsWithPartial.sort().forEach(component => { + console.info(`❌ Did not move '${component}' due to usage as a "partial"`); + }); + + templateFilePaths = templateFilePaths.filter(templateFilePath => { + // Extract '/app/templates/components/nested1/nested-component.hbs' + let filePathFromApp = templateFilePath.slice(this.projectRoot.length); + + if (/\/\-[\w\-]+\.hbs/.test(filePathFromApp)) { + filePathFromApp = filePathFromApp.replace('/-', '/'); + } + + // Extract '/components/nested1/nested-component.hbs' + const filePathFromAppTemplates = filePathFromApp.slice('app/templates/'.length); + + // Extract 'components/nested1/nested-component' + const classFilePath = filePathFromAppTemplates.slice(1).replace('.hbs', ''); + + return !componentsWithPartial.includes(classFilePath); + }); + } + + return templateFilePaths; + } + async removeEmptyClassicComponentDirectories(removeOnlyEmptyDirectories) { const templateFolderPath = path.join(this.projectRoot, 'app/templates/components'); @@ -69,21 +98,9 @@ module.exports = class Migrator { let classFilePaths = this.findClassicComponentClasses(); templateFilePaths = this.skipTemplatesUsedAsLayoutName(templateFilePaths); + templateFilePaths = this.skipTemplatesUsedAsPartial(templateFilePaths); - let sourceTemplateFilePaths = this.findTemplates(); - let templatesInPartials = getPartialTemplates(sourceTemplateFilePaths); - if (templatesInPartials.length) { - templateFilePaths = templateFilePaths.filter(sourceTemplateFilePath => { - let sourceTemplatePathInApp = sourceTemplateFilePath.slice(this.projectRoot.length); // '/app/templates/components/nested1/nested-component.hbs' - if (/\/\-[\w\-]+\.hbs/.test(sourceTemplatePathInApp)) { - sourceTemplatePathInApp = sourceTemplatePathInApp.replace('/-', '/'); - } - let templatePath = sourceTemplatePathInApp.slice('app/templates/'.length); // '/nested1/nested-component.hbs' - return !templatesInPartials.includes(templatePath.slice(1).replace('.hbs', '')); - }); - } - templateFilePaths.forEach(sourceTemplateFilePath => { let sourceTemplatePathInApp = sourceTemplateFilePath.slice(this.projectRoot.length); // '/app/templates/components/nested1/nested-component.hbs' let templatePath = sourceTemplatePathInApp.slice('app/templates/components/'.length); // '/nested1/nested-component.hbs' @@ -93,11 +110,6 @@ module.exports = class Migrator { const templatesWithLayoutName = getLayoutNameTemplates(classFilePaths); - - templatesInPartials.sort().forEach(template => { - console.info(`❌ Did not move '${template}' due to usage as a "partial"`); - }); - const removeOnlyEmptyDirectories = Boolean(templatesWithLayoutName.length); await this.removeEmptyClassicComponentDirectories(removeOnlyEmptyDirectories); } From e264611827ea39fb0028412dbece6e156789dd16 Mon Sep 17 00:00:00 2001 From: ijlee2 Date: Sun, 26 Apr 2020 16:53:49 -0500 Subject: [PATCH 10/23] Refactored migrator by creating changeComponentStructureToFlat method --- lib/migrator.js | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/lib/migrator.js b/lib/migrator.js index 23a464e..389682f 100644 --- a/lib/migrator.js +++ b/lib/migrator.js @@ -87,6 +87,20 @@ module.exports = class Migrator { return templateFilePaths; } + changeComponentStructureToFlat(templateFilePaths) { + templateFilePaths.forEach(templateFilePath => { + // Extract '/app/templates/components/nested1/nested-component.hbs' + const filePathFromApp = templateFilePath.slice(this.projectRoot.length); + + // Extract '/nested1/nested-component.hbs' + const filePathFromAppTemplatesComponents = filePathFromApp.slice('app/templates/components/'.length); + + // '[APP_PATH]/app/components/nested1/nested-component.hbs' + const newTemplateFilePath = path.join(this.projectRoot, 'app/components', filePathFromAppTemplatesComponents); + moveFile(templateFilePath, newTemplateFilePath); + }); + } + async removeEmptyClassicComponentDirectories(removeOnlyEmptyDirectories) { const templateFolderPath = path.join(this.projectRoot, 'app/templates/components'); @@ -100,14 +114,7 @@ module.exports = class Migrator { templateFilePaths = this.skipTemplatesUsedAsLayoutName(templateFilePaths); templateFilePaths = this.skipTemplatesUsedAsPartial(templateFilePaths); - - templateFilePaths.forEach(sourceTemplateFilePath => { - let sourceTemplatePathInApp = sourceTemplateFilePath.slice(this.projectRoot.length); // '/app/templates/components/nested1/nested-component.hbs' - let templatePath = sourceTemplatePathInApp.slice('app/templates/components/'.length); // '/nested1/nested-component.hbs' - let targetTemplateFilePath = path.join(this.projectRoot, 'app/components', templatePath); // '[APP_PATH]/app/components/nested1/nested-component.hbs' - moveFile(sourceTemplateFilePath, targetTemplateFilePath); - }); - + this.changeComponentStructureToFlat(templateFilePaths); const templatesWithLayoutName = getLayoutNameTemplates(classFilePaths); const removeOnlyEmptyDirectories = Boolean(templatesWithLayoutName.length); From 840a89ced5d5432699051bf59a28f90110a32aee Mon Sep 17 00:00:00 2001 From: ijlee2 Date: Sun, 26 Apr 2020 16:58:15 -0500 Subject: [PATCH 11/23] Refactored migrator by adding a better separation of concerns between removeEmptyClassicComponentDirectories and execute --- lib/migrator.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/lib/migrator.js b/lib/migrator.js index 389682f..44eb713 100644 --- a/lib/migrator.js +++ b/lib/migrator.js @@ -101,23 +101,24 @@ module.exports = class Migrator { }); } - async removeEmptyClassicComponentDirectories(removeOnlyEmptyDirectories) { + async removeEmptyClassicComponentDirectories() { const templateFolderPath = path.join(this.projectRoot, 'app/templates/components'); + + const classFilePaths = this.findClassicComponentClasses(); + const templatesWithLayoutName = getLayoutNameTemplates(classFilePaths); + const removeOnlyEmptyDirectories = Boolean(templatesWithLayoutName.length); await removeDirs(templateFolderPath, removeOnlyEmptyDirectories); } async execute() { let templateFilePaths = this.findClassicComponentTemplates(); - let classFilePaths = this.findClassicComponentClasses(); - templateFilePaths = this.skipTemplatesUsedAsLayoutName(templateFilePaths); templateFilePaths = this.skipTemplatesUsedAsPartial(templateFilePaths); this.changeComponentStructureToFlat(templateFilePaths); - const templatesWithLayoutName = getLayoutNameTemplates(classFilePaths); - const removeOnlyEmptyDirectories = Boolean(templatesWithLayoutName.length); - await this.removeEmptyClassicComponentDirectories(removeOnlyEmptyDirectories); + // Clean up + await this.removeEmptyClassicComponentDirectories(); } } \ No newline at end of file From b5b6c266ce0d3b504b00ec0a468d17e23b8cd469 Mon Sep 17 00:00:00 2001 From: ijlee2 Date: Sun, 26 Apr 2020 16:58:51 -0500 Subject: [PATCH 12/23] Moved logging to migrator class methods --- lib/migrator.js | 4 ++++ lib/utils/templates.js | 2 -- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/migrator.js b/lib/migrator.js index 44eb713..9a0d27f 100644 --- a/lib/migrator.js +++ b/lib/migrator.js @@ -33,6 +33,8 @@ module.exports = class Migrator { } skipTemplatesUsedAsLayoutName(templateFilePaths) { + console.info(`\nChecking if any component templates are used as templates of other components using \`layoutName\``); + const classFilePaths = this.findClassicComponentClasses(); const componentsWithLayoutName = getLayoutNameTemplates(classFilePaths); @@ -59,6 +61,8 @@ module.exports = class Migrator { } skipTemplatesUsedAsPartial(templateFilePaths) { + console.info(`\nChecking if any component templates are used as partials`); + const componentsWithPartial = getPartialTemplates(this.findTemplates()); if (componentsWithPartial.length) { diff --git a/lib/utils/templates.js b/lib/utils/templates.js index 7bf9b8a..77fc010 100644 --- a/lib/utils/templates.js +++ b/lib/utils/templates.js @@ -4,7 +4,6 @@ const jsTraverse = require('@babel/traverse').default; const { parse, traverse } = require('ember-template-recast'); function getLayoutNameTemplates(files) { - console.info(`Checking if any component templates are used as templates of other components using \`layoutName\``); let names = files.map(file => { let content = readFileSync(file, 'utf8'); return fileInLayoutName(content); @@ -33,7 +32,6 @@ function fileInLayoutName(content) { } function getPartialTemplates(files) { - console.info(`Checking if any component templates are used as partials`); let names = files.reduce((acc, file) => { let content = readFileSync(file, 'utf8'); let partials = filesInPartials(content); From e48d94ef0f98dcd7e65fb69e8d5706ce0748fa1f Mon Sep 17 00:00:00 2001 From: ijlee2 Date: Sun, 26 Apr 2020 17:04:43 -0500 Subject: [PATCH 13/23] Allowed passing newComponentStructure to Migrator class --- bin/ember-component-template-colocation-migrator | 7 ++++++- lib/migrator.js | 7 +++++-- test/migrator-test.js | 5 ++++- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/bin/ember-component-template-colocation-migrator b/bin/ember-component-template-colocation-migrator index ad9a37d..84cece2 100755 --- a/bin/ember-component-template-colocation-migrator +++ b/bin/ember-component-template-colocation-migrator @@ -14,7 +14,12 @@ let options = { let parsed = nopt(options); let projectRoot = parsed['project-root'] || process.cwd(); -let migrator = new Migrator({ projectRoot }); +let newComponentStructure = 'flat'; + +let migrator = new Migrator({ + projectRoot, + newComponentStructure +}); migrator.execute().then(function() { console.log('Codemod finished successfully!'); diff --git a/lib/migrator.js b/lib/migrator.js index 9a0d27f..fcc8cc3 100644 --- a/lib/migrator.js +++ b/lib/migrator.js @@ -6,9 +6,10 @@ const { moveFile, removeDirs } = require('./utils/file') module.exports = class Migrator { constructor(options) { - const { projectRoot } = options; + const { projectRoot, newComponentStructure } = options; this.projectRoot = projectRoot; + this.newComponentStructure = newComponentStructure; } findClassicComponentTemplates() { @@ -120,7 +121,9 @@ module.exports = class Migrator { templateFilePaths = this.skipTemplatesUsedAsLayoutName(templateFilePaths); templateFilePaths = this.skipTemplatesUsedAsPartial(templateFilePaths); - this.changeComponentStructureToFlat(templateFilePaths); + if (this.newComponentStructure === 'flat') { + this.changeComponentStructureToFlat(templateFilePaths); + } // Clean up await this.removeEmptyClassicComponentDirectories(); diff --git a/test/migrator-test.js b/test/migrator-test.js index 230640a..f7a5ca0 100644 --- a/test/migrator-test.js +++ b/test/migrator-test.js @@ -38,7 +38,10 @@ describe("Migrator", function() { fixturify.writeSync(tmpPath, input); var migratorOptions = Object.assign( - { projectRoot: tmpPath }, + { + projectRoot: tmpPath, + newComponentStructure: 'flat' + }, migratorConfig ); From a4d81f4b0f9e5ec527bf783b8669c0dd897606ee Mon Sep 17 00:00:00 2001 From: ijlee2 Date: Sun, 26 Apr 2020 17:06:54 -0500 Subject: [PATCH 14/23] Reorganized test fixtures in preparation for testing nested component structure --- .../classic-to-flat/{ => example-1}/input.js | 0 .../classic-to-flat/{ => example-1}/output.js | 0 test/migrator-test.js | 85 ++++++++++--------- 3 files changed, 43 insertions(+), 42 deletions(-) rename test/fixtures/classic-to-flat/{ => example-1}/input.js (100%) rename test/fixtures/classic-to-flat/{ => example-1}/output.js (100%) diff --git a/test/fixtures/classic-to-flat/input.js b/test/fixtures/classic-to-flat/example-1/input.js similarity index 100% rename from test/fixtures/classic-to-flat/input.js rename to test/fixtures/classic-to-flat/example-1/input.js diff --git a/test/fixtures/classic-to-flat/output.js b/test/fixtures/classic-to-flat/example-1/output.js similarity index 100% rename from test/fixtures/classic-to-flat/output.js rename to test/fixtures/classic-to-flat/example-1/output.js diff --git a/test/migrator-test.js b/test/migrator-test.js index f7a5ca0..ff0b5bb 100644 --- a/test/migrator-test.js +++ b/test/migrator-test.js @@ -10,50 +10,51 @@ var Migrator = require('../lib/migrator'); assertDiff.options.strict = true; describe("Migrator", function() { - var tmpPath = "tmp/process-files"; - var fixturesPath = path.resolve(__dirname, "fixtures"); + describe('newComponentStructure = flat', function() { + var tmpPath = "tmp/process-files"; + var fixturesPath = path.resolve(__dirname, "fixtures/classic-to-flat"); - beforeEach(function() { - fse.mkdirsSync(tmpPath); - }); + beforeEach(function() { + fse.mkdirsSync(tmpPath); + }); - afterEach(function() { - fse.removeSync(tmpPath); - }); + afterEach(function() { + fse.removeSync(tmpPath); + }); - var entries = fse.readdirSync(fixturesPath); - - entries.forEach(async function(entry) { - it(`should migrate ${entry} fixture properly`, async function() { - var fixturePath = path.join(fixturesPath, entry); - var input = require(fixturePath + "/input"); - var expected = require(fixturePath + "/output"); - var migratorConfig = {}; - try { - migratorConfig = require(fixturePath + "/config"); - } catch (e) { - // fixture uses default config... - } - - fixturify.writeSync(tmpPath, input); - - var migratorOptions = Object.assign( - { - projectRoot: tmpPath, - newComponentStructure: 'flat' - }, - migratorConfig - ); - - var migrator = new Migrator(migratorOptions); - await migrator.execute(); - - var actual = fixturify.readSync(tmpPath); - assertDiff.deepEqual(actual, expected, "the codemod should work as expected"); - - await migrator.execute(); - assertDiff.deepEqual(actual, expected, "the codemod should be idempotent"); + var entries = fse.readdirSync(fixturesPath); + + entries.forEach(async function(entry) { + it(`should migrate ${entry} fixture properly`, async function() { + var fixturePath = path.join(fixturesPath, entry); + var input = require(fixturePath + "/input"); + var expected = require(fixturePath + "/output"); + var migratorConfig = {}; + try { + migratorConfig = require(fixturePath + "/config"); + } catch (e) { + // fixture uses default config... + } + + fixturify.writeSync(tmpPath, input); + + var migratorOptions = Object.assign( + { + projectRoot: tmpPath, + newComponentStructure: 'flat' + }, + migratorConfig + ); + + var migrator = new Migrator(migratorOptions); + await migrator.execute(); + + var actual = fixturify.readSync(tmpPath); + assertDiff.deepEqual(actual, expected, "the codemod should work as expected"); + + await migrator.execute(); + assertDiff.deepEqual(actual, expected, "the codemod should be idempotent"); + }); }); }); -}); - +}); \ No newline at end of file From 161e9fa6ff8c15e163c3afded7407d869f31c3da Mon Sep 17 00:00:00 2001 From: ijlee2 Date: Sun, 26 Apr 2020 17:09:15 -0500 Subject: [PATCH 15/23] Added test example for migrating to nested component structure --- .../classic-to-nested/example-1/input.js | 78 ++++++++++++++++++ .../classic-to-nested/example-1/output.js | 80 +++++++++++++++++++ 2 files changed, 158 insertions(+) create mode 100644 test/fixtures/classic-to-nested/example-1/input.js create mode 100644 test/fixtures/classic-to-nested/example-1/output.js diff --git a/test/fixtures/classic-to-nested/example-1/input.js b/test/fixtures/classic-to-nested/example-1/input.js new file mode 100644 index 0000000..14b6d93 --- /dev/null +++ b/test/fixtures/classic-to-nested/example-1/input.js @@ -0,0 +1,78 @@ +module.exports = { + app: { + 'app.js': '// app', + + components: { + // A standalone component + 'top-level-component.js': '// top-level-component.js', + + // A nested component + 'parent-component.js': '// parent-component.js', + 'parent-component': { + 'child-component.js': '// parent-component/child-component.js', + 'child-component': { + 'grandchild-component.js': '// parent-component/child-component/grandchild-component.js' + } + }, + + // Another nested component + nested1: { + 'nested-component.js': '// nested1/nested-component.js', + nested2: { + 'super-nested-component.js': '// nested1/nested2/super-nested-component.js' + } + }, + + // A component with layoutName + 'layout-name': { + 'has-layout-name.js': [ + '// top-level-component.js', + 'Component.extend({ layoutName: "components/layout-name/layout-name-template" });' + ].join('\n') + } + }, + + templates: { + 'application.hbs': '{{outlet}}', + + components: { + // A standalone component + 'top-level-component.hbs': '{{!-- top-level-component.hbs --}}', + + // A template-only component + 'template-only-component.hbs': '{{!-- template-only-component.hbs --}}', + + // A nested component + 'parent-component.hbs': '{{!-- parent-component.hbs --}}', + 'parent-component': { + 'child-component.hbs': '{{!-- parent-component/child-component.hbs --}}', + 'child-component': { + 'grandchild-component.hbs': '{{!-- parent-component/child-component/grandchild-component.hbs --}}' + } + }, + + // Another nested component + nested1: { + 'nested-component.hbs': '{{!-- nested1/nested-component.hbs --}}', + nested2: { + 'super-nested-component.hbs': '{{!-- nested1/nested2/super-nested-component.hbs --}}' + } + }, + + // A component with layoutName + 'layout-name': { + 'layout-name-template.hbs': '{{!-- layout-name-template.hbs --}}' + }, + + // A partial template + 'partials': { + 'partials-template.hbs': '{{!-- partials-template.hbs --}}', + 'with-partial.hbs': [ + '{{!-- with-partial.hbs --}}', + '{{partial "components/partials/partials-template"}}' + ].join('\n') + } + } + } + } +}; \ No newline at end of file diff --git a/test/fixtures/classic-to-nested/example-1/output.js b/test/fixtures/classic-to-nested/example-1/output.js new file mode 100644 index 0000000..18cf682 --- /dev/null +++ b/test/fixtures/classic-to-nested/example-1/output.js @@ -0,0 +1,80 @@ +module.exports = { + app: { + 'app.js': '// app', + + components: { + // A standalone component + 'top-level-component': { + 'index.hbs': '{{!-- top-level-component.hbs --}}', + 'index.js': '// top-level-component.js', + }, + + // A template-only component + 'template-only-component': { + 'index.hbs': '{{!-- template-only-component.hbs --}}' + }, + + // A nested component + 'parent-component': { + 'index.hbs': '{{!-- parent-component.hbs --}}', + 'index.js': '// parent-component.js', + 'child-component': { + 'index.hbs': '{{!-- parent-component/child-component.hbs --}}', + 'index.js': '// parent-component/child-component.js', + 'grandchild-component': { + 'index.hbs': '{{!-- parent-component/child-component/grandchild-component.hbs --}}', + 'index.js': '// parent-component/child-component/grandchild-component.js' + } + } + }, + + // Another nested component + nested1: { + 'nested-component': { + 'index.hbs': '{{!-- nested1/nested-component.hbs --}}', + 'index.js': '// nested1/nested-component.js', + }, + nested2: { + 'super-nested-component': { + 'index.hbs': '{{!-- nested1/nested2/super-nested-component.hbs --}}', + 'index.js': '// nested1/nested2/super-nested-component.js' + } + } + }, + + // A component with layoutName + 'layout-name': { + 'has-layout-name.js': [ + '// top-level-component.js', + 'Component.extend({ layoutName: "components/layout-name/layout-name-template" });' + ].join('\n') + }, + + // A component with partial + 'partials': { + 'with-partial': { + 'index.hbs': [ + '{{!-- with-partial.hbs --}}', + '{{partial "components/partials/partials-template"}}' + ].join('\n') + } + } + }, + + templates: { + 'application.hbs': '{{outlet}}', + + components: { + // A component with layoutName + 'layout-name': { + 'layout-name-template.hbs': '{{!-- layout-name-template.hbs --}}' + }, + + // A partial template + 'partials': { + 'partials-template.hbs': '{{!-- partials-template.hbs --}}', + } + } + } + }, +}; \ No newline at end of file From f534b56c159221d17fde33a7bc26c269f30757ba Mon Sep 17 00:00:00 2001 From: ijlee2 Date: Sun, 26 Apr 2020 18:43:34 -0500 Subject: [PATCH 16/23] Created changeComponentStructureToNested method --- lib/migrator.js | 32 ++++++++++++++++++++++++++++ test/migrator-test.js | 49 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) diff --git a/lib/migrator.js b/lib/migrator.js index fcc8cc3..972e018 100644 --- a/lib/migrator.js +++ b/lib/migrator.js @@ -106,6 +106,34 @@ module.exports = class Migrator { }); } + changeComponentStructureToNested(templateFilePaths) { + const classFilePaths = this.findClassicComponentClasses(); + + templateFilePaths.forEach(templateFilePath => { + // Extract '/app/templates/components/nested1/nested-component.hbs' + const filePathFromApp = templateFilePath.slice(this.projectRoot.length); + + // Extract '/nested1/nested-component.hbs' + const filePathFromAppTemplatesComponents = filePathFromApp.slice('app/templates/components/'.length); + const fileExtension = path.extname(filePathFromAppTemplatesComponents); + + // Extract '/nested1/nested-component' + const targetPath = filePathFromAppTemplatesComponents.slice(0, -fileExtension.length); + + // Build '[APP_PATH]/app/components/nested1/nested-component/index.hbs' + const newTemplateFilePath = path.join(this.projectRoot, 'app/components', targetPath, 'index.hbs'); + moveFile(templateFilePath, newTemplateFilePath); + + // Build '[APP_PATH]/app/components/nested1/nested-component/index.js' + const classFilePath = path.join(this.projectRoot, 'app/components', `${targetPath}.js`); + + if (classFilePaths.includes(classFilePath)) { + const newClassFilePath = path.join(this.projectRoot, 'app/components', targetPath, 'index.js'); + moveFile(classFilePath, newClassFilePath); + } + }); + } + async removeEmptyClassicComponentDirectories() { const templateFolderPath = path.join(this.projectRoot, 'app/templates/components'); @@ -123,6 +151,10 @@ module.exports = class Migrator { if (this.newComponentStructure === 'flat') { this.changeComponentStructureToFlat(templateFilePaths); + + } else if (this.newComponentStructure === 'nested') { + this.changeComponentStructureToNested(templateFilePaths); + } // Clean up diff --git a/test/migrator-test.js b/test/migrator-test.js index ff0b5bb..c189ea8 100644 --- a/test/migrator-test.js +++ b/test/migrator-test.js @@ -57,4 +57,53 @@ describe("Migrator", function() { }); }); }); + + + describe('newComponentStructure = nested', function() { + var tmpPath = "tmp/process-files"; + var fixturesPath = path.resolve(__dirname, "fixtures/classic-to-nested"); + + beforeEach(function() { + fse.mkdirsSync(tmpPath); + }); + + afterEach(function() { + fse.removeSync(tmpPath); + }); + + var entries = fse.readdirSync(fixturesPath); + + entries.forEach(async function(entry) { + it(`should migrate ${entry} fixture properly`, async function() { + var fixturePath = path.join(fixturesPath, entry); + var input = require(fixturePath + "/input"); + var expected = require(fixturePath + "/output"); + var migratorConfig = {}; + try { + migratorConfig = require(fixturePath + "/config"); + } catch (e) { + // fixture uses default config... + } + + fixturify.writeSync(tmpPath, input); + + var migratorOptions = Object.assign( + { + projectRoot: tmpPath, + newComponentStructure: 'nested' + }, + migratorConfig + ); + + var migrator = new Migrator(migratorOptions); + await migrator.execute(); + + var actual = fixturify.readSync(tmpPath); + assertDiff.deepEqual(actual, expected, "the codemod should work as expected"); + + await migrator.execute(); + assertDiff.deepEqual(actual, expected, "the codemod should be idempotent"); + }); + }); + }); }); \ No newline at end of file From e92bb50578809a402180fab9ad701cd7f6225d08 Mon Sep 17 00:00:00 2001 From: ijlee2 Date: Sun, 26 Apr 2020 18:45:00 -0500 Subject: [PATCH 17/23] Allowed passing -ns flag to migrate to nested component structure --- README.md | 39 ++++++++++++++++++- ...ber-component-template-colocation-migrator | 13 ++++++- 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 23bfe78..1648454 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,43 @@ cd your/project/path npx github:ember-codemods/ember-component-template-colocation-migrator ``` +By default, the migrator changes the **classic** component structure to the **flat** component structure. + +``` +your-project-name +├── app +│ └── components +│ ├── foo-bar +│ │ ├── baz.hbs +│ │ └── baz.js +│ ├── foo-bar.hbs +│ └── foo-bar.js +│ ... +``` + +If you want to change from **classic** to **nested**, you can add the `-ns` flag: + +```sh +cd your/project/path +npx github:ember-codemods/ember-component-template-colocation-migrator -ns +``` + +The nested component structure looks like: + +``` +your-project-name +├── app +│ └── components +│ └── foo-bar +│ ├── baz +│ │ ├── index.hbs +│ │ └── index.js +│ ├── index.hbs +│ └── index.js +│ ... +``` + + ### Running Tests - * `npm run test` + * `npm run test` \ No newline at end of file diff --git a/bin/ember-component-template-colocation-migrator b/bin/ember-component-template-colocation-migrator index 84cece2..34fa1fd 100755 --- a/bin/ember-component-template-colocation-migrator +++ b/bin/ember-component-template-colocation-migrator @@ -14,8 +14,19 @@ let options = { let parsed = nopt(options); let projectRoot = parsed['project-root'] || process.cwd(); +const args = process.argv.slice(2); + +// Allow passing the flag, -fs (flat) or -ns (nested), to specify component structure let newComponentStructure = 'flat'; +if (args.includes('-fs')) { + newComponentStructure = 'flat'; + +} else if (args.includes('-ns')) { + newComponentStructure = 'nested'; + +} + let migrator = new Migrator({ projectRoot, newComponentStructure @@ -25,4 +36,4 @@ migrator.execute().then(function() { console.log('Codemod finished successfully!'); }).catch(function(error) { console.error(error.stack); -}); +}); \ No newline at end of file From 4c2ffb64c3f980d2742db411519f4fb3893cb132 Mon Sep 17 00:00:00 2001 From: ijlee2 Date: Mon, 27 Apr 2020 14:42:07 -0500 Subject: [PATCH 18/23] Installed yargs to parse command line options --- ...ber-component-template-colocation-migrator | 9 +- package.json | 3 +- yarn.lock | 104 ++++++++++++++++++ 3 files changed, 112 insertions(+), 4 deletions(-) diff --git a/bin/ember-component-template-colocation-migrator b/bin/ember-component-template-colocation-migrator index 34fa1fd..c44ccec 100755 --- a/bin/ember-component-template-colocation-migrator +++ b/bin/ember-component-template-colocation-migrator @@ -14,15 +14,18 @@ let options = { let parsed = nopt(options); let projectRoot = parsed['project-root'] || process.cwd(); -const args = process.argv.slice(2); +const { argv } = require('yargs'); // Allow passing the flag, -fs (flat) or -ns (nested), to specify component structure +const changeToFlatStructure = argv.f && argv.s; +const changeToNestedStructure = argv.n && argv.s; + let newComponentStructure = 'flat'; -if (args.includes('-fs')) { +if (changeToFlatStructure) { newComponentStructure = 'flat'; -} else if (args.includes('-ns')) { +} else if (changeToNestedStructure) { newComponentStructure = 'nested'; } diff --git a/package.json b/package.json index 0357618..abdb191 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,8 @@ "fs-extra": "^7.0.1", "glob": "^7.1.4", "nopt": "^4.0.1", - "remove-empty-directories": "^0.0.1" + "remove-empty-directories": "^0.0.1", + "yargs": "^15.3.1" }, "repository": { "type": "git", diff --git a/yarn.lock b/yarn.lock index 6abd070..3af5daa 100644 --- a/yarn.lock +++ b/yarn.lock @@ -330,6 +330,14 @@ ansi-styles@^3.2.1: dependencies: color-convert "^1.9.0" +ansi-styles@^4.0.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.2.1.tgz#90ae75c424d008d2624c5bf29ead3177ebfcf359" + integrity sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA== + dependencies: + "@types/color-name" "^1.1.1" + color-convert "^2.0.1" + ansi-styles@^4.1.0: version "4.2.0" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.2.0.tgz#5681f0dcf7ae5880a7841d8831c4724ed9cc0172" @@ -463,6 +471,15 @@ cliui@^4.0.0: strip-ansi "^4.0.0" wrap-ansi "^2.0.0" +cliui@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" + integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^6.2.0" + clone@^1.0.2: version "1.0.4" resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" @@ -636,6 +653,11 @@ emoji-regex@^7.0.1: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + empower-core@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/empower-core/-/empower-core-1.2.0.tgz#ce3fb2484d5187fa29c23fba8344b0b2fdf5601c" @@ -769,6 +791,14 @@ find-up@3.0.0, find-up@^3.0.0: dependencies: locate-path "^3.0.0" +find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + fixturify@^1.0.1: version "1.2.0" resolved "https://registry.yarnpkg.com/fixturify/-/fixturify-1.2.0.tgz#abe8c52dd27dbbfdb874a02893781c93425663ea" @@ -998,6 +1028,11 @@ is-fullwidth-code-point@^2.0.0: resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + is-glob@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" @@ -1095,6 +1130,13 @@ locate-path@^3.0.0: p-locate "^3.0.0" path-exists "^3.0.0" +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14: version "4.17.15" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" @@ -1380,6 +1422,13 @@ p-limit@^2.0.0: dependencies: p-try "^2.0.0" +p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + p-locate@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" @@ -1387,6 +1436,13 @@ p-locate@^3.0.0: dependencies: p-limit "^2.0.0" +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + p-try@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" @@ -1397,6 +1453,11 @@ path-exists@^3.0.0: resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" @@ -1672,6 +1733,15 @@ string-width@^3.0.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^5.1.0" +string-width@^4.1.0, string-width@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" + integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.0" + stringifier@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/stringifier/-/stringifier-1.4.0.tgz#d704581567f4526265d00ed8ecb354a02c3fec28" @@ -1845,6 +1915,15 @@ wrap-ansi@^2.0.0: string-width "^1.0.1" strip-ansi "^3.0.1" +wrap-ansi@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" + integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" @@ -1884,6 +1963,14 @@ yargs-parser@^13.0.0: camelcase "^5.0.0" decamelize "^1.2.0" +yargs-parser@^18.1.1: + version "18.1.3" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" + integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + yargs-unparser@1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-1.5.0.tgz#f2bb2a7e83cbc87bb95c8e572828a06c9add6e0d" @@ -1927,3 +2014,20 @@ yargs@^12.0.5: which-module "^2.0.0" y18n "^3.2.1 || ^4.0.0" yargs-parser "^11.1.1" + +yargs@^15.3.1: + version "15.3.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.3.1.tgz#9505b472763963e54afe60148ad27a330818e98b" + integrity sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA== + dependencies: + cliui "^6.0.0" + decamelize "^1.2.0" + find-up "^4.1.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^4.2.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^18.1.1" From 777712ea673d125b73122a2712f1946ece8684d4 Mon Sep 17 00:00:00 2001 From: ijlee2 Date: Mon, 27 Apr 2020 14:44:10 -0500 Subject: [PATCH 19/23] Renamed the class field newComponentStructure to structure --- bin/ember-component-template-colocation-migrator | 11 ++++------- lib/migrator.js | 8 ++++---- test/migrator-test.js | 8 ++++---- 3 files changed, 12 insertions(+), 15 deletions(-) diff --git a/bin/ember-component-template-colocation-migrator b/bin/ember-component-template-colocation-migrator index c44ccec..5ffefc8 100755 --- a/bin/ember-component-template-colocation-migrator +++ b/bin/ember-component-template-colocation-migrator @@ -20,20 +20,17 @@ const { argv } = require('yargs'); const changeToFlatStructure = argv.f && argv.s; const changeToNestedStructure = argv.n && argv.s; -let newComponentStructure = 'flat'; +let structure = 'flat'; if (changeToFlatStructure) { - newComponentStructure = 'flat'; + structure = 'flat'; } else if (changeToNestedStructure) { - newComponentStructure = 'nested'; + structure = 'nested'; } -let migrator = new Migrator({ - projectRoot, - newComponentStructure -}); +let migrator = new Migrator({ projectRoot, structure }); migrator.execute().then(function() { console.log('Codemod finished successfully!'); diff --git a/lib/migrator.js b/lib/migrator.js index 972e018..e9714a4 100644 --- a/lib/migrator.js +++ b/lib/migrator.js @@ -6,10 +6,10 @@ const { moveFile, removeDirs } = require('./utils/file') module.exports = class Migrator { constructor(options) { - const { projectRoot, newComponentStructure } = options; + const { projectRoot, structure } = options; this.projectRoot = projectRoot; - this.newComponentStructure = newComponentStructure; + this.structure = structure; } findClassicComponentTemplates() { @@ -149,10 +149,10 @@ module.exports = class Migrator { templateFilePaths = this.skipTemplatesUsedAsLayoutName(templateFilePaths); templateFilePaths = this.skipTemplatesUsedAsPartial(templateFilePaths); - if (this.newComponentStructure === 'flat') { + if (this.structure === 'flat') { this.changeComponentStructureToFlat(templateFilePaths); - } else if (this.newComponentStructure === 'nested') { + } else if (this.structure === 'nested') { this.changeComponentStructureToNested(templateFilePaths); } diff --git a/test/migrator-test.js b/test/migrator-test.js index c189ea8..8af18f6 100644 --- a/test/migrator-test.js +++ b/test/migrator-test.js @@ -10,7 +10,7 @@ var Migrator = require('../lib/migrator'); assertDiff.options.strict = true; describe("Migrator", function() { - describe('newComponentStructure = flat', function() { + describe('structure = flat', function() { var tmpPath = "tmp/process-files"; var fixturesPath = path.resolve(__dirname, "fixtures/classic-to-flat"); @@ -41,7 +41,7 @@ describe("Migrator", function() { var migratorOptions = Object.assign( { projectRoot: tmpPath, - newComponentStructure: 'flat' + structure: 'flat' }, migratorConfig ); @@ -59,7 +59,7 @@ describe("Migrator", function() { }); - describe('newComponentStructure = nested', function() { + describe('structure = nested', function() { var tmpPath = "tmp/process-files"; var fixturesPath = path.resolve(__dirname, "fixtures/classic-to-nested"); @@ -90,7 +90,7 @@ describe("Migrator", function() { var migratorOptions = Object.assign( { projectRoot: tmpPath, - newComponentStructure: 'nested' + structure: 'nested' }, migratorConfig ); From d9f847fae6e0dc9250a2925681109f28d922635a Mon Sep 17 00:00:00 2001 From: ijlee2 Date: Tue, 28 Apr 2020 10:23:22 -0500 Subject: [PATCH 20/23] Added a newline at the end of the file --- bin/ember-component-template-colocation-migrator | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/ember-component-template-colocation-migrator b/bin/ember-component-template-colocation-migrator index 5ffefc8..f167f58 100755 --- a/bin/ember-component-template-colocation-migrator +++ b/bin/ember-component-template-colocation-migrator @@ -36,4 +36,4 @@ migrator.execute().then(function() { console.log('Codemod finished successfully!'); }).catch(function(error) { console.error(error.stack); -}); \ No newline at end of file +}); From 107260838c62935b1bdfde95e8d7adcdbeec5504 Mon Sep 17 00:00:00 2001 From: ijlee2 Date: Tue, 28 Apr 2020 16:17:58 -0500 Subject: [PATCH 21/23] Documented what the regular expression /\/\-[\w\-]+\.hbs/ does --- lib/migrator.js | 9 +++++++++ test/fixtures/classic-to-flat/example-1/input.js | 9 +++++++-- test/fixtures/classic-to-flat/example-1/output.js | 8 ++++++-- test/fixtures/classic-to-nested/example-1/input.js | 9 +++++++-- test/fixtures/classic-to-nested/example-1/output.js | 8 ++++++-- 5 files changed, 35 insertions(+), 8 deletions(-) diff --git a/lib/migrator.js b/lib/migrator.js index e9714a4..e00c3b7 100644 --- a/lib/migrator.js +++ b/lib/migrator.js @@ -75,6 +75,15 @@ module.exports = class Migrator { // Extract '/app/templates/components/nested1/nested-component.hbs' let filePathFromApp = templateFilePath.slice(this.projectRoot.length); + /* + When Ember sees `{{partial "foo"}}`, it will look for the template in + two locations: + + - `app/templates/foo.hbs` + - `app/templates/-foo.hbs` + + If `filePathFromApp` matches the latter pattern, we remove the hyphen. + */ if (/\/\-[\w\-]+\.hbs/.test(filePathFromApp)) { filePathFromApp = filePathFromApp.replace('/-', '/'); } diff --git a/test/fixtures/classic-to-flat/example-1/input.js b/test/fixtures/classic-to-flat/example-1/input.js index 14b6d93..205c4ca 100644 --- a/test/fixtures/classic-to-flat/example-1/input.js +++ b/test/fixtures/classic-to-flat/example-1/input.js @@ -66,10 +66,15 @@ module.exports = { // A partial template 'partials': { - 'partials-template.hbs': '{{!-- partials-template.hbs --}}', + 'partial-one-template.hbs': '{{!-- partial-one-template.hbs --}}', + 'partial-two-template.hbs': '{{!-- partial-two-template.hbs --}}', + '-partial-three-template.hbs': '{{!-- partial-three-template.hbs --}}', + 'with-partial.hbs': [ '{{!-- with-partial.hbs --}}', - '{{partial "components/partials/partials-template"}}' + '{{partial "components/partials/partial-one-template"}}', + '{{partial "components/partials/partial-two-template"}}', + '{{partial "components/partials/partial-three-template"}}' ].join('\n') } } diff --git a/test/fixtures/classic-to-flat/example-1/output.js b/test/fixtures/classic-to-flat/example-1/output.js index 97aa7f7..d5b3d1f 100644 --- a/test/fixtures/classic-to-flat/example-1/output.js +++ b/test/fixtures/classic-to-flat/example-1/output.js @@ -44,7 +44,9 @@ module.exports = { 'partials': { 'with-partial.hbs': [ '{{!-- with-partial.hbs --}}', - '{{partial "components/partials/partials-template"}}' + '{{partial "components/partials/partial-one-template"}}', + '{{partial "components/partials/partial-two-template"}}', + '{{partial "components/partials/partial-three-template"}}' ].join('\n') } }, @@ -60,7 +62,9 @@ module.exports = { // A partial template 'partials': { - 'partials-template.hbs': '{{!-- partials-template.hbs --}}', + 'partial-one-template.hbs': '{{!-- partial-one-template.hbs --}}', + 'partial-two-template.hbs': '{{!-- partial-two-template.hbs --}}', + '-partial-three-template.hbs': '{{!-- partial-three-template.hbs --}}' } } } diff --git a/test/fixtures/classic-to-nested/example-1/input.js b/test/fixtures/classic-to-nested/example-1/input.js index 14b6d93..205c4ca 100644 --- a/test/fixtures/classic-to-nested/example-1/input.js +++ b/test/fixtures/classic-to-nested/example-1/input.js @@ -66,10 +66,15 @@ module.exports = { // A partial template 'partials': { - 'partials-template.hbs': '{{!-- partials-template.hbs --}}', + 'partial-one-template.hbs': '{{!-- partial-one-template.hbs --}}', + 'partial-two-template.hbs': '{{!-- partial-two-template.hbs --}}', + '-partial-three-template.hbs': '{{!-- partial-three-template.hbs --}}', + 'with-partial.hbs': [ '{{!-- with-partial.hbs --}}', - '{{partial "components/partials/partials-template"}}' + '{{partial "components/partials/partial-one-template"}}', + '{{partial "components/partials/partial-two-template"}}', + '{{partial "components/partials/partial-three-template"}}' ].join('\n') } } diff --git a/test/fixtures/classic-to-nested/example-1/output.js b/test/fixtures/classic-to-nested/example-1/output.js index 18cf682..a5d92e0 100644 --- a/test/fixtures/classic-to-nested/example-1/output.js +++ b/test/fixtures/classic-to-nested/example-1/output.js @@ -55,7 +55,9 @@ module.exports = { 'with-partial': { 'index.hbs': [ '{{!-- with-partial.hbs --}}', - '{{partial "components/partials/partials-template"}}' + '{{partial "components/partials/partial-one-template"}}', + '{{partial "components/partials/partial-two-template"}}', + '{{partial "components/partials/partial-three-template"}}' ].join('\n') } } @@ -72,7 +74,9 @@ module.exports = { // A partial template 'partials': { - 'partials-template.hbs': '{{!-- partials-template.hbs --}}', + 'partial-one-template.hbs': '{{!-- partial-one-template.hbs --}}', + 'partial-two-template.hbs': '{{!-- partial-two-template.hbs --}}', + '-partial-three-template.hbs': '{{!-- partial-three-template.hbs --}}' } } } From da8cd91cb3019d9f7f79381a31ac19360e7cc111 Mon Sep 17 00:00:00 2001 From: ijlee2 Date: Tue, 28 Apr 2020 17:05:31 -0500 Subject: [PATCH 22/23] Renamed the fixture folder from example-1 to example-js --- test/fixtures/classic-to-flat/{example-1 => example-js}/input.js | 0 test/fixtures/classic-to-flat/{example-1 => example-js}/output.js | 0 .../fixtures/classic-to-nested/{example-1 => example-js}/input.js | 0 .../classic-to-nested/{example-1 => example-js}/output.js | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename test/fixtures/classic-to-flat/{example-1 => example-js}/input.js (100%) rename test/fixtures/classic-to-flat/{example-1 => example-js}/output.js (100%) rename test/fixtures/classic-to-nested/{example-1 => example-js}/input.js (100%) rename test/fixtures/classic-to-nested/{example-1 => example-js}/output.js (100%) diff --git a/test/fixtures/classic-to-flat/example-1/input.js b/test/fixtures/classic-to-flat/example-js/input.js similarity index 100% rename from test/fixtures/classic-to-flat/example-1/input.js rename to test/fixtures/classic-to-flat/example-js/input.js diff --git a/test/fixtures/classic-to-flat/example-1/output.js b/test/fixtures/classic-to-flat/example-js/output.js similarity index 100% rename from test/fixtures/classic-to-flat/example-1/output.js rename to test/fixtures/classic-to-flat/example-js/output.js diff --git a/test/fixtures/classic-to-nested/example-1/input.js b/test/fixtures/classic-to-nested/example-js/input.js similarity index 100% rename from test/fixtures/classic-to-nested/example-1/input.js rename to test/fixtures/classic-to-nested/example-js/input.js diff --git a/test/fixtures/classic-to-nested/example-1/output.js b/test/fixtures/classic-to-nested/example-js/output.js similarity index 100% rename from test/fixtures/classic-to-nested/example-1/output.js rename to test/fixtures/classic-to-nested/example-js/output.js From 23766e20abfc60e7abfe104760bf4b423e20d68b Mon Sep 17 00:00:00 2001 From: ijlee2 Date: Tue, 28 Apr 2020 17:07:49 -0500 Subject: [PATCH 23/23] Added support for moving component classes written in TypeScript --- lib/migrator.js | 16 +++- .../classic-to-flat/example-ts/input.js | 83 ++++++++++++++++++ .../classic-to-flat/example-ts/output.js | 72 ++++++++++++++++ .../classic-to-nested/example-ts/input.js | 83 ++++++++++++++++++ .../classic-to-nested/example-ts/output.js | 84 +++++++++++++++++++ 5 files changed, 334 insertions(+), 4 deletions(-) create mode 100644 test/fixtures/classic-to-flat/example-ts/input.js create mode 100644 test/fixtures/classic-to-flat/example-ts/output.js create mode 100644 test/fixtures/classic-to-nested/example-ts/input.js create mode 100644 test/fixtures/classic-to-nested/example-ts/output.js diff --git a/lib/migrator.js b/lib/migrator.js index e00c3b7..a4871f9 100644 --- a/lib/migrator.js +++ b/lib/migrator.js @@ -21,7 +21,7 @@ module.exports = class Migrator { findClassicComponentClasses() { const classFolderPath = path.join(this.projectRoot, 'app/components'); - const classFilePaths = glob.sync(`${classFolderPath}/**/*.js`); + const classFilePaths = glob.sync(`${classFolderPath}/**/*.{js,ts}`); return classFilePaths; } @@ -134,11 +134,19 @@ module.exports = class Migrator { moveFile(templateFilePath, newTemplateFilePath); // Build '[APP_PATH]/app/components/nested1/nested-component/index.js' - const classFilePath = path.join(this.projectRoot, 'app/components', `${targetPath}.js`); + const classFilePath = { + js: path.join(this.projectRoot, 'app/components', `${targetPath}.js`), + ts: path.join(this.projectRoot, 'app/components', `${targetPath}.ts`) + }; - if (classFilePaths.includes(classFilePath)) { + if (classFilePaths.includes(classFilePath.js)) { const newClassFilePath = path.join(this.projectRoot, 'app/components', targetPath, 'index.js'); - moveFile(classFilePath, newClassFilePath); + moveFile(classFilePath.js, newClassFilePath); + + } else if (classFilePaths.includes(classFilePath.ts)) { + const newClassFilePath = path.join(this.projectRoot, 'app/components', targetPath, 'index.ts'); + moveFile(classFilePath.ts, newClassFilePath); + } }); } diff --git a/test/fixtures/classic-to-flat/example-ts/input.js b/test/fixtures/classic-to-flat/example-ts/input.js new file mode 100644 index 0000000..4c46edc --- /dev/null +++ b/test/fixtures/classic-to-flat/example-ts/input.js @@ -0,0 +1,83 @@ +module.exports = { + app: { + 'app.js': '// app', + + components: { + // A standalone component + 'top-level-component.ts': '// top-level-component.ts', + + // A nested component + 'parent-component.ts': '// parent-component.ts', + 'parent-component': { + 'child-component.ts': '// parent-component/child-component.ts', + 'child-component': { + 'grandchild-component.ts': '// parent-component/child-component/grandchild-component.ts' + } + }, + + // Another nested component + nested1: { + 'nested-component.ts': '// nested1/nested-component.ts', + nested2: { + 'super-nested-component.ts': '// nested1/nested2/super-nested-component.ts' + } + }, + + // A component with layoutName + 'layout-name': { + 'has-layout-name.ts': [ + '// top-level-component.ts', + 'Component.extend({ layoutName: "components/layout-name/layout-name-template" });' + ].join('\n') + } + }, + + templates: { + 'application.hbs': '{{outlet}}', + + components: { + // A standalone component + 'top-level-component.hbs': '{{!-- top-level-component.hbs --}}', + + // A template-only component + 'template-only-component.hbs': '{{!-- template-only-component.hbs --}}', + + // A nested component + 'parent-component.hbs': '{{!-- parent-component.hbs --}}', + 'parent-component': { + 'child-component.hbs': '{{!-- parent-component/child-component.hbs --}}', + 'child-component': { + 'grandchild-component.hbs': '{{!-- parent-component/child-component/grandchild-component.hbs --}}' + } + }, + + // Another nested component + nested1: { + 'nested-component.hbs': '{{!-- nested1/nested-component.hbs --}}', + nested2: { + 'super-nested-component.hbs': '{{!-- nested1/nested2/super-nested-component.hbs --}}' + } + }, + + // A component with layoutName + 'layout-name': { + 'layout-name-template.hbs': '{{!-- layout-name-template.hbs --}}' + }, + + // A partial template + 'partials': { + 'partial-one-template.hbs': '{{!-- partial-one-template.hbs --}}', + 'partial-two-template.hbs': '{{!-- partial-two-template.hbs --}}', + '-partial-three-template.hbs': '{{!-- partial-three-template.hbs --}}', + + 'with-partial.hbs': [ + '{{!-- with-partial.hbs --}}', + '{{partial "components/partials/partial-one-template"}}', + '{{partial "components/partials/partial-two-template"}}', + '{{partial "components/partials/partial-three-template"}}' + ].join('\n') + } + } + } + } +}; \ No newline at end of file diff --git a/test/fixtures/classic-to-flat/example-ts/output.js b/test/fixtures/classic-to-flat/example-ts/output.js new file mode 100644 index 0000000..d91acc7 --- /dev/null +++ b/test/fixtures/classic-to-flat/example-ts/output.js @@ -0,0 +1,72 @@ +module.exports = { + app: { + 'app.js': '// app', + + components: { + // A standalone component + 'top-level-component.hbs': '{{!-- top-level-component.hbs --}}', + 'top-level-component.ts': '// top-level-component.ts', + + // A template-only component + 'template-only-component.hbs': '{{!-- template-only-component.hbs --}}', + + // A nested component + 'parent-component.hbs': '{{!-- parent-component.hbs --}}', + 'parent-component.ts': '// parent-component.ts', + 'parent-component': { + 'child-component.hbs': '{{!-- parent-component/child-component.hbs --}}', + 'child-component.ts': '// parent-component/child-component.ts', + 'child-component': { + 'grandchild-component.hbs': '{{!-- parent-component/child-component/grandchild-component.hbs --}}', + 'grandchild-component.ts': '// parent-component/child-component/grandchild-component.ts' + } + }, + + // Another nested component + nested1: { + 'nested-component.hbs': '{{!-- nested1/nested-component.hbs --}}', + 'nested-component.ts': '// nested1/nested-component.ts', + nested2: { + 'super-nested-component.hbs': '{{!-- nested1/nested2/super-nested-component.hbs --}}', + 'super-nested-component.ts': '// nested1/nested2/super-nested-component.ts' + } + }, + + // A component with layoutName + 'layout-name': { + 'has-layout-name.ts': [ + '// top-level-component.ts', + 'Component.extend({ layoutName: "components/layout-name/layout-name-template" });' + ].join('\n') + }, + + // A component with partial + 'partials': { + 'with-partial.hbs': [ + '{{!-- with-partial.hbs --}}', + '{{partial "components/partials/partial-one-template"}}', + '{{partial "components/partials/partial-two-template"}}', + '{{partial "components/partials/partial-three-template"}}' + ].join('\n') + } + }, + + templates: { + 'application.hbs': '{{outlet}}', + + components: { + // A component with layoutName + 'layout-name': { + 'layout-name-template.hbs': '{{!-- layout-name-template.hbs --}}' + }, + + // A partial template + 'partials': { + 'partial-one-template.hbs': '{{!-- partial-one-template.hbs --}}', + 'partial-two-template.hbs': '{{!-- partial-two-template.hbs --}}', + '-partial-three-template.hbs': '{{!-- partial-three-template.hbs --}}' + } + } + } + }, +}; \ No newline at end of file diff --git a/test/fixtures/classic-to-nested/example-ts/input.js b/test/fixtures/classic-to-nested/example-ts/input.js new file mode 100644 index 0000000..4c46edc --- /dev/null +++ b/test/fixtures/classic-to-nested/example-ts/input.js @@ -0,0 +1,83 @@ +module.exports = { + app: { + 'app.js': '// app', + + components: { + // A standalone component + 'top-level-component.ts': '// top-level-component.ts', + + // A nested component + 'parent-component.ts': '// parent-component.ts', + 'parent-component': { + 'child-component.ts': '// parent-component/child-component.ts', + 'child-component': { + 'grandchild-component.ts': '// parent-component/child-component/grandchild-component.ts' + } + }, + + // Another nested component + nested1: { + 'nested-component.ts': '// nested1/nested-component.ts', + nested2: { + 'super-nested-component.ts': '// nested1/nested2/super-nested-component.ts' + } + }, + + // A component with layoutName + 'layout-name': { + 'has-layout-name.ts': [ + '// top-level-component.ts', + 'Component.extend({ layoutName: "components/layout-name/layout-name-template" });' + ].join('\n') + } + }, + + templates: { + 'application.hbs': '{{outlet}}', + + components: { + // A standalone component + 'top-level-component.hbs': '{{!-- top-level-component.hbs --}}', + + // A template-only component + 'template-only-component.hbs': '{{!-- template-only-component.hbs --}}', + + // A nested component + 'parent-component.hbs': '{{!-- parent-component.hbs --}}', + 'parent-component': { + 'child-component.hbs': '{{!-- parent-component/child-component.hbs --}}', + 'child-component': { + 'grandchild-component.hbs': '{{!-- parent-component/child-component/grandchild-component.hbs --}}' + } + }, + + // Another nested component + nested1: { + 'nested-component.hbs': '{{!-- nested1/nested-component.hbs --}}', + nested2: { + 'super-nested-component.hbs': '{{!-- nested1/nested2/super-nested-component.hbs --}}' + } + }, + + // A component with layoutName + 'layout-name': { + 'layout-name-template.hbs': '{{!-- layout-name-template.hbs --}}' + }, + + // A partial template + 'partials': { + 'partial-one-template.hbs': '{{!-- partial-one-template.hbs --}}', + 'partial-two-template.hbs': '{{!-- partial-two-template.hbs --}}', + '-partial-three-template.hbs': '{{!-- partial-three-template.hbs --}}', + + 'with-partial.hbs': [ + '{{!-- with-partial.hbs --}}', + '{{partial "components/partials/partial-one-template"}}', + '{{partial "components/partials/partial-two-template"}}', + '{{partial "components/partials/partial-three-template"}}' + ].join('\n') + } + } + } + } +}; \ No newline at end of file diff --git a/test/fixtures/classic-to-nested/example-ts/output.js b/test/fixtures/classic-to-nested/example-ts/output.js new file mode 100644 index 0000000..fcaa4b8 --- /dev/null +++ b/test/fixtures/classic-to-nested/example-ts/output.js @@ -0,0 +1,84 @@ +module.exports = { + app: { + 'app.js': '// app', + + components: { + // A standalone component + 'top-level-component': { + 'index.hbs': '{{!-- top-level-component.hbs --}}', + 'index.ts': '// top-level-component.ts', + }, + + // A template-only component + 'template-only-component': { + 'index.hbs': '{{!-- template-only-component.hbs --}}' + }, + + // A nested component + 'parent-component': { + 'index.hbs': '{{!-- parent-component.hbs --}}', + 'index.ts': '// parent-component.ts', + 'child-component': { + 'index.hbs': '{{!-- parent-component/child-component.hbs --}}', + 'index.ts': '// parent-component/child-component.ts', + 'grandchild-component': { + 'index.hbs': '{{!-- parent-component/child-component/grandchild-component.hbs --}}', + 'index.ts': '// parent-component/child-component/grandchild-component.ts' + } + } + }, + + // Another nested component + nested1: { + 'nested-component': { + 'index.hbs': '{{!-- nested1/nested-component.hbs --}}', + 'index.ts': '// nested1/nested-component.ts', + }, + nested2: { + 'super-nested-component': { + 'index.hbs': '{{!-- nested1/nested2/super-nested-component.hbs --}}', + 'index.ts': '// nested1/nested2/super-nested-component.ts' + } + } + }, + + // A component with layoutName + 'layout-name': { + 'has-layout-name.ts': [ + '// top-level-component.ts', + 'Component.extend({ layoutName: "components/layout-name/layout-name-template" });' + ].join('\n') + }, + + // A component with partial + 'partials': { + 'with-partial': { + 'index.hbs': [ + '{{!-- with-partial.hbs --}}', + '{{partial "components/partials/partial-one-template"}}', + '{{partial "components/partials/partial-two-template"}}', + '{{partial "components/partials/partial-three-template"}}' + ].join('\n') + } + } + }, + + templates: { + 'application.hbs': '{{outlet}}', + + components: { + // A component with layoutName + 'layout-name': { + 'layout-name-template.hbs': '{{!-- layout-name-template.hbs --}}' + }, + + // A partial template + 'partials': { + 'partial-one-template.hbs': '{{!-- partial-one-template.hbs --}}', + 'partial-two-template.hbs': '{{!-- partial-two-template.hbs --}}', + '-partial-three-template.hbs': '{{!-- partial-three-template.hbs --}}' + } + } + } + }, +}; \ No newline at end of file