Skip to content

Commit ce248a2

Browse files
committed
template-only-glimmer-components: Add support for pods and mixed layouts
1 parent fe5fcc9 commit ce248a2

File tree

2 files changed

+203
-23
lines changed

2 files changed

+203
-23
lines changed

features/template-only-glimmer-components.js

Lines changed: 64 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -32,33 +32,78 @@ module.exports = {
3232
}
3333

3434
let root = project.root;
35-
let prefix = project.config().podModulePrefix;
36-
let isPod = !!prefix;
35+
let projectConfig = project.config();
36+
37+
let { modulePrefix, podModulePrefix } = projectConfig;
38+
let podsFolder;
39+
if (podModulePrefix) {
40+
if (!modulePrefix || !podModulePrefix.startsWith(`${modulePrefix}/`)) {
41+
console.log(chalk.yellow(`${chalk.bold('Note:')} There is an automated refactor script available for this feature, but your \`podModulePrefix\` could not be processed correctly.\n`));
42+
return;
43+
}
44+
45+
podsFolder = podModulePrefix.slice(modulePrefix.length + 1);
46+
if (!podsFolder) {
47+
console.log(chalk.yellow(`${chalk.bold('Note:')} There is an automated refactor script available for this feature, but your \`podModulePrefix\` could not be processed correctly.\n`));
48+
return;
49+
}
50+
}
3751

3852
let templates = [];
3953
let components = [];
4054

41-
if (isPod) {
42-
// TODO
43-
console.log(chalk.yellow(`${chalk.bold('Note:')} There is an automated refactor script available for this feature, but it does not currently support "pod" apps. PRs welcome!\n`));
44-
return;
45-
} else {
46-
let templatesRoot = path.join(root, 'app/templates/components');
47-
let templateCandidates = yield p(glob)('**/*.hbs', { cwd: templatesRoot });
55+
// Handle "Classic" layout
56+
let templatesRoot = path.join(root, 'app/templates/components');
57+
let templateCandidates = yield p(glob)('**/*.hbs', { cwd: templatesRoot });
4858

49-
templateCandidates.forEach(template => {
50-
let templatePath = path.join('app/templates/components', template);
59+
templateCandidates.forEach(template => {
60+
let templatePath = path.join('app/templates/components', template);
5161

52-
let jsPath = path.join('app/components', template.replace(/\.hbs$/, '.js'));
53-
if (fs.existsSync(path.join(root, jsPath))) return;
62+
let jsPath = path.join('app/components', template.replace(/\.hbs$/, '.js'));
63+
if (fs.existsSync(path.join(root, jsPath))) return;
5464

55-
let tsPath = path.join('app/components', template.replace(/\.hbs$/, '.ts'));
56-
if (fs.existsSync(path.join(root, tsPath))) return;
65+
let tsPath = path.join('app/components', template.replace(/\.hbs$/, '.ts'));
66+
if (fs.existsSync(path.join(root, tsPath))) return;
5767

58-
templates.push(templatePath);
59-
components.push(jsPath); // Always offer to create JS
60-
});
61-
}
68+
templates.push(templatePath);
69+
components.push(jsPath); // Always offer to create JS
70+
});
71+
72+
// Handle "Pods" layout without prefix
73+
74+
let componentsRoot = path.join(root, 'app/components');
75+
templateCandidates = yield p(glob)('**/template.hbs', { cwd: componentsRoot });
76+
77+
templateCandidates.forEach(template => {
78+
let templatePath = path.join('app/components', template);
79+
80+
let jsPath = path.join('app/components', template.replace(/template\.hbs$/, 'component.js'));
81+
if (fs.existsSync(path.join(root, jsPath))) return;
82+
83+
let tsPath = path.join('app/components', template.replace(/template\.hbs$/, 'component.ts'));
84+
if (fs.existsSync(path.join(root, tsPath))) return;
85+
86+
templates.push(templatePath);
87+
components.push(jsPath); // Always offer to create JS
88+
});
89+
90+
// Handle "Pods" layout *with* prefix
91+
92+
componentsRoot = path.join(root, `app/${podsFolder}/components`);
93+
templateCandidates = yield p(glob)('**/template.hbs', { cwd: componentsRoot });
94+
95+
templateCandidates.forEach(template => {
96+
let templatePath = path.join(`app/${podsFolder}/components`, template);
97+
98+
let jsPath = path.join(`app/${podsFolder}/components`, template.replace(/template\.hbs$/, 'component.js'));
99+
if (fs.existsSync(path.join(root, jsPath))) return;
100+
101+
let tsPath = path.join(`app/${podsFolder}/components`, template.replace(/template\.hbs$/, 'component.ts'));
102+
if (fs.existsSync(path.join(root, tsPath))) return;
103+
104+
templates.push(templatePath);
105+
components.push(jsPath); // Always offer to create JS
106+
});
62107

63108
if (templates.length === 0) {
64109
return;

tests/commands-test.js

Lines changed: 139 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,106 @@ QUnit.module('commands', hooks => {
349349
}
350350
};
351351

352+
const PODS_AFTER = {
353+
pods: {
354+
components: {
355+
'foo-bar': {
356+
'component.js': componentJS,
357+
'template.hbs': '<!-- foo-bar -->',
358+
},
359+
'another': {
360+
'component.js': componentJS,
361+
'template.hbs': '<!-- another -->',
362+
},
363+
'also-not-component': {
364+
'something.txt': 'This is not a component file.'
365+
},
366+
'not-template-only': {
367+
'component.js': '/* do not touch */',
368+
'template.hbs': '<!-- not-template-only -->',
369+
},
370+
'ts-not-template-only': {
371+
'component.ts': '/* do not touch */',
372+
'template.hbs': '<!-- not-template-only -->',
373+
},
374+
},
375+
'not-component': {
376+
'template.hbs': '<!-- route template -->',
377+
},
378+
}
379+
};
380+
381+
const MIXED_BEFORE = {
382+
components: {
383+
'not-template-only-pods': {
384+
'component.js': '/* not-template-only-pods */',
385+
'template.hbs': '<!-- not-template-only-pods -->',
386+
},
387+
'template-only-pods': {
388+
'template.hbs': '<!-- template-only-pods -->',
389+
},
390+
'not-template-only.js': '/* not-template-only */',
391+
},
392+
pods: {
393+
components: {
394+
'not-template-only-pods-prefix': {
395+
'component.js': '/* not-template-only-pods-prefix */',
396+
'template.hbs': '<!-- not-template-only-pods-prefix -->',
397+
},
398+
'template-only-pods-prefix': {
399+
'template.hbs': '<!-- template-only-pods-prefix -->',
400+
},
401+
},
402+
'not-component-pods-prefix': {
403+
'template.hbs': '<!-- not-component-pods-prefix -->',
404+
},
405+
},
406+
templates: {
407+
components: {
408+
'not-template-only.hbs': '<!-- not-template-only -->',
409+
'template-only.hbs': '<!-- template-only -->',
410+
},
411+
'not-component.hbs': '<!-- not-component -->',
412+
},
413+
};
414+
415+
const MIXED_AFTER = {
416+
components: {
417+
'not-template-only-pods': {
418+
'component.js': '/* not-template-only-pods */',
419+
'template.hbs': '<!-- not-template-only-pods -->',
420+
},
421+
'template-only-pods': {
422+
'component.js': componentJS,
423+
'template.hbs': '<!-- template-only-pods -->',
424+
},
425+
'not-template-only.js': '/* not-template-only */',
426+
'template-only.js': componentJS,
427+
},
428+
pods: {
429+
components: {
430+
'not-template-only-pods-prefix': {
431+
'component.js': '/* not-template-only-pods-prefix */',
432+
'template.hbs': '<!-- not-template-only-pods-prefix -->',
433+
},
434+
'template-only-pods-prefix': {
435+
'component.js': componentJS,
436+
'template.hbs': '<!-- template-only-pods-prefix -->',
437+
},
438+
},
439+
'not-component-pods-prefix': {
440+
'template.hbs': '<!-- not-component-pods-prefix -->',
441+
},
442+
},
443+
templates: {
444+
components: {
445+
'not-template-only.hbs': '<!-- not-template-only -->',
446+
'template-only.hbs': '<!-- template-only -->',
447+
},
448+
'not-component.hbs': '<!-- not-component -->',
449+
},
450+
};
451+
352452
QUnit.test('it generates component files when asked to', co.wrap(function *(assert) {
353453
project.write({ app: CLASSIC_BEFORE });
354454

@@ -357,22 +457,40 @@ QUnit.module('commands', hooks => {
357457
assert.deepEqual(project.read('app'), CLASSIC_AFTER, 'it should have generated the component JS files');
358458
}));
359459

360-
QUnit.test('it shows a warning when `podModulePrefix` is set', co.wrap(function *(assert) {
460+
QUnit.test('it works for pods', co.wrap(function *(assert) {
361461
project.write({
362462
app: PODS_BEFORE,
363463
config: {
364464
'environment.js': `module.exports = function() {
365-
return {
465+
return {
366466
modulePrefix: 'my-app',
367467
podModulePrefix: 'my-app/pods',
368468
};
369469
};`
370470
}
371471
});
372472

373-
let result = yield run('feature:enable', 'template-only-glimmer-components', { input: 'yes\n' });
473+
yield run('feature:enable', 'template-only-glimmer-components', { input: 'yes\n' });
474+
475+
assert.deepEqual(project.read('app'), PODS_AFTER, 'it should have generated the component JS files');
476+
}));
477+
478+
QUnit.test('it works for mixed layout apps', co.wrap(function *(assert) {
479+
project.write({
480+
app: MIXED_BEFORE,
481+
config: {
482+
'environment.js': `module.exports = function() {
483+
return {
484+
modulePrefix: 'my-app',
485+
podModulePrefix: 'my-app/pods',
486+
};
487+
};`
488+
}
489+
});
490+
491+
yield run('feature:enable', 'template-only-glimmer-components', { input: 'yes\n' });
374492

375-
assert.ok(result.stdout.includes('There is an automated refactor script available for this feature, but it does not currently support "pod" apps.'))
493+
assert.deepEqual(project.read('app'), MIXED_AFTER, 'it should have generated the component JS files');
376494
}));
377495

378496
QUnit.test('it does not generates component files when asked not to', co.wrap(function *(assert) {
@@ -382,5 +500,22 @@ QUnit.module('commands', hooks => {
382500

383501
assert.deepEqual(project.read('app'), CLASSIC_BEFORE, 'it should have generated the component JS files');
384502
}));
503+
504+
QUnit.test('it fails for missing `modulePrefix` when `podModulePrefix` is set', co.wrap(function *(assert) {
505+
project.write({
506+
app: PODS_BEFORE,
507+
config: {
508+
'environment.js': `module.exports = function() {
509+
return {
510+
podModulePrefix: 'my-app/pods',
511+
};
512+
};`
513+
}
514+
});
515+
516+
let result = yield run('feature:enable', 'template-only-glimmer-components', { input: 'yes\n' });
517+
518+
assert.ok(result.stdout.includes('`podModulePrefix` could not be processed correctly'));
519+
}));
385520
});
386521
});

0 commit comments

Comments
 (0)