Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for nested component structure #11

Merged
merged 23 commits into from Apr 29, 2020
Merged
Changes from 7 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
ef070c2
Renamed the folder to classic-to-flat
ijlee2 Apr 26, 2020
79b0eaf
Added test examples of a "typical" nested component and a template-on…
ijlee2 Apr 26, 2020
590a2b1
Stored projectRoot as a class field
ijlee2 Apr 26, 2020
9b6be57
Refactored migrator by creating findClassicComponentTemplates and rem…
ijlee2 Apr 26, 2020
ed9725c
Refactored migrator by creating findClassicComponentClasses method
ijlee2 Apr 26, 2020
a689def
Shortened variable names for readability
ijlee2 Apr 26, 2020
e3953ff
Refactored migrator by creating skipTemplatesUsedAsLayoutName method
ijlee2 Apr 26, 2020
e660109
Refactored migrator by creating findTemplates method
ijlee2 Apr 26, 2020
43d6225
Refactored migrator by creating skipTemplatesUsedAsPartial method
ijlee2 Apr 26, 2020
e264611
Refactored migrator by creating changeComponentStructureToFlat method
ijlee2 Apr 26, 2020
840a89c
Refactored migrator by adding a better separation of concerns between…
ijlee2 Apr 26, 2020
b5b6c26
Moved logging to migrator class methods
ijlee2 Apr 26, 2020
e48d94e
Allowed passing newComponentStructure to Migrator class
ijlee2 Apr 26, 2020
a4d81f4
Reorganized test fixtures in preparation for testing nested component…
ijlee2 Apr 26, 2020
161e9fa
Added test example for migrating to nested component structure
ijlee2 Apr 26, 2020
f534b56
Created changeComponentStructureToNested method
ijlee2 Apr 26, 2020
e92bb50
Allowed passing -ns flag to migrate to nested component structure
ijlee2 Apr 26, 2020
4c2ffb6
Installed yargs to parse command line options
ijlee2 Apr 27, 2020
777712e
Renamed the class field newComponentStructure to structure
ijlee2 Apr 27, 2020
d9f847f
Added a newline at the end of the file
ijlee2 Apr 28, 2020
1072608
Documented what the regular expression /\/\-[\w\-]+\.hbs/ does
ijlee2 Apr 28, 2020
da8cd91
Renamed the fixture folder from example-1 to example-js
ijlee2 Apr 28, 2020
23766e2
Added support for moving component classes written in TypeScript
ijlee2 Apr 28, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -11,50 +11,113 @@ module.exports = class Migrator {
this.projectRoot = projectRoot;
}

async execute() {
let sourceComponentTemplatesPath = path.join(this.projectRoot, 'app/templates/components');
var sourceComponentTemplateFilePaths = glob.sync(`${sourceComponentTemplatesPath}/**/*.hbs`);

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.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', ''));
findClassicComponentTemplates() {
const templateFolderPath = path.join(this.projectRoot, 'app/templates/components');
const templateFilePaths = glob.sync(`${templateFolderPath}/**/*.hbs`);

return templateFilePaths;
}

findClassicComponentClasses() {
const classFolderPath = path.join(this.projectRoot, 'app/components');
const classFilePaths = glob.sync(`${classFolderPath}/**/*.js`);

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);

if (componentsWithLayoutName.length) {
componentsWithLayoutName.sort().forEach(component => {
console.info(`❌ Did not move '${component}' due to usage as "layoutName" in a component`);
Copy link
Member

@rwjblue rwjblue Apr 27, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably tell them which component

Copy link
Contributor Author

@ijlee2 ijlee2 Apr 28, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, can you elaborate on what you'd like the log message to say?

I only renamed the value for forEach from template to component:

// Before
templatesWithLayoutName.sort().forEach(template => {
  console.info(`❌ Did not move '${template}' due to usage as "layoutName" in a component`);
});

// After
componentsWithLayoutName.sort().forEach(component => {
  console.info(`❌ Did not move '${component}' due to usage as "layoutName" in a component`);
});

A test run shows that the log message currently looks like:

❌ Did not move 'components/layout-name/layout-name-template' due to usage as "layoutName" in a component

Copy link
Member

@rwjblue rwjblue Apr 29, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ya, I think its fine (didn't notice that it was only a small tweak) for now. I was thinking that saying the template and the component that we found using it for layoutName would be helpful.

});

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);
});
}

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.projectRoot.length); // '/app/templates/components/nested1/nested-component.hbs'
if (/\/\-[\w\-]+\.hbs/.test(sourceTemplatePathInApp)) {
sourceTemplatePathInApp = sourceTemplatePathInApp.replace('/-', '/');
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"`);
Copy link
Member

@rwjblue rwjblue Apr 27, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should probably say where the {{partial invocation was found

Copy link
Contributor Author

@ijlee2 ijlee2 Apr 28, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you elaborate on what you'd like the log message to say?

A test run shows that the log message currently looks like:

❌ Did not move 'components/partials/partials-template' due to usage as a "partial"

Copy link
Member

@rwjblue rwjblue Apr 29, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Basically to say the template name (which the message does now) and the name of hte template that uses it as a partial.

Did not move 'components/partials/partials-template' due to usage as a "partial" in 'templates/index.hbs'

});

templateFilePaths = templateFilePaths.filter(templateFilePath => {
// Extract '/app/templates/components/nested1/nested-component.hbs'
let filePathFromApp = templateFilePath.slice(this.projectRoot.length);

if (/\/\-[\w\-]+\.hbs/.test(filePathFromApp)) {
Copy link
Contributor Author

@ijlee2 ijlee2 Apr 26, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure what lines 73-75 were for. This check didn't appear in skipTemplatesUsedAsLayoutName and wasn't evaluated to be true in tests.

Copy link
Member

@rwjblue rwjblue Apr 27, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When Ember sees {{partial "foo"}} it will look in to locations:

  • app/templates/foo.hbs
  • app/templates/-foo.hbs

I think this is attempting to identify when -foo.hbs format is used, and still match {{partial "foo"}}?

filePathFromApp = filePathFromApp.replace('/-', '/');
}
let templatePath = sourceTemplatePathInApp.slice('app/templates/'.length); // '/nested1/nested-component.hbs'
return !templatesInPartials.includes(templatePath.slice(1).replace('.hbs', ''));

// 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);
});
}

sourceComponentTemplateFilePaths.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);
});
return templateFilePaths;
}

templatesWithLayoutName.sort().forEach(template => {
console.info(`❌ Did not move '${template}' due to usage as "layoutName" in a component`);
});
templatesInPartials.sort().forEach(template => {
console.info(`❌ Did not move '${template}' due to usage as a "partial"`);
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');

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);

let onlyRemoveEmptyDirs = Boolean(templatesWithLayoutName.length);
await removeDirs(sourceComponentTemplatesPath, onlyRemoveEmptyDirs);
const templatesWithLayoutName = getLayoutNameTemplates(classFilePaths);
const removeOnlyEmptyDirectories = Boolean(templatesWithLayoutName.length);
await this.removeEmptyClassicComponentDirectories(removeOnlyEmptyDirectories);
}
}