Skip to content

Commit 60ed734

Browse files
authored
Merge pull request #2 from GavinJoyce/gj/initial
Implement initial codemod
2 parents 343663f + 6f59389 commit 60ed734

File tree

9 files changed

+1396
-1
lines changed

9 files changed

+1396
-1
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/node_modules
2+
/tmp

REAME.md

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,21 @@
11
# ember-component-template-colocation
22

3-
This is a WIP codemod which aims to implement https://emberjs.github.io/rfcs/0481-component-templates-co-location.html
3+
This codemod will co-locate component JS and HBS as described in the [Component Templates Co-location RFC](https://emberjs.github.io/rfcs/0481-component-templates-co-location.html).
4+
5+
### Examples
6+
7+
* [Travis CI](https://github.com/GavinJoyce/travis-web/pull/1)
8+
* [Ghost Admin](https://github.com/GavinJoyce/Ghost-Admin/pull/1)
9+
10+
### Usage
11+
12+
To run the migrator on your app:
13+
14+
```sh
15+
cd your/project/path
16+
npx github:gavinjoyce/ember-component-template-colocation-migrator
17+
```
18+
19+
### Running Tests
20+
21+
* `npm run test`
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#!/usr/bin/env node
2+
'use strict';
3+
4+
// Provide a title to the process in `ps`
5+
process.title = 'ember-component-template-colocation-migrator';
6+
7+
let fs = require('fs');
8+
let Migrator = require('../lib/migrator');
9+
let nopt = require("nopt");
10+
let options = {
11+
'project-root': [String]
12+
};
13+
14+
let parsed = nopt(options);
15+
let projectRoot = parsed['project-root'] || process.cwd();
16+
17+
let migrator = new Migrator({ projectRoot });
18+
19+
migrator.execute().then(function() {
20+
console.log('Codemod finished successfully!');
21+
}).catch(function(error) {
22+
console.error(error.stack);
23+
});

lib/migrator.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
var fse = require("fs-extra");
2+
var path = require('path');
3+
var glob = require("glob");
4+
5+
function moveFile(sourceFilePath, targetFilePath) {
6+
let targetFileDirectory = path.dirname(targetFilePath);
7+
if (!fse.existsSync(targetFileDirectory)) {
8+
console.info(`📁 Creating ${targetFileDirectory}`);
9+
fse.mkdirSync(targetFileDirectory, { recursive: true })
10+
}
11+
12+
console.info(`👍 Moving ${sourceFilePath} -> ${targetFilePath}`);
13+
fse.renameSync(sourceFilePath, targetFilePath);
14+
}
15+
16+
module.exports = class Migrator {
17+
constructor(options) {
18+
this.options = options;
19+
}
20+
21+
async execute() {
22+
let sourceComponentTemplatesPath = path.join(this.options.projectRoot, 'app/templates/components');
23+
var sourceTemplateFilePaths = glob.sync(`${sourceComponentTemplatesPath}/**/*.hbs`);
24+
25+
sourceTemplateFilePaths.forEach(sourceTemplateFilePath => {
26+
let sourceTemplatePathInApp = sourceTemplateFilePath.slice(this.options.projectRoot.length); // '/app/templates/components/nested1/nested-component.hbs'
27+
let templatePath = sourceTemplatePathInApp.slice('app/templates/components/'.length); // '/nested1/nested-component.hbs'
28+
let targetTemplateFilePath = path.join(this.options.projectRoot, 'app/components', templatePath); // '[APP_PATH]/app/components/nested1/nested-component.hbs'
29+
moveFile(sourceTemplateFilePath, targetTemplateFilePath);
30+
});
31+
32+
await fse.remove(sourceComponentTemplatesPath);
33+
}
34+
}

package.json

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{
2+
"name": "ember-component-template-colocation-migrator",
3+
"version": "1.0.0",
4+
"description": "A codemod that moves your component .hbs files to be co-located with their .js",
5+
"author": "Gavin Joyce <gavinjoyce@gmail.com>",
6+
"license": "MIT",
7+
"main": "lib/index.js",
8+
"bin": {
9+
"ember-component-template-colocation-migrator": "./bin/ember-component-template-colocation-migrator"
10+
},
11+
"scripts": {
12+
"test": "mocha test/*-test.js test/**/*-test.js"
13+
},
14+
"devDependencies": {
15+
"assert-diff": "^2.0.3",
16+
"fixturify": "^1.0.1",
17+
"mocha": "^6.1.1",
18+
"power-assert": "^1.3.1"
19+
},
20+
"dependencies": {
21+
"fs-extra": "^7.0.1",
22+
"glob": "^7.1.4",
23+
"nopt": "^4.0.1"
24+
},
25+
"repository": {
26+
"type": "git",
27+
"url": "git+https://github.com/GavinJoyce/ember-component-template-colocation-migrator.git"
28+
},
29+
"bugs": {
30+
"url": "https://github.com/GavinJoyce/ember-component-template-colocation-migrator/issues"
31+
},
32+
"homepage": "https://github.com/GavinJoyce/ember-component-template-colocation-migrator#readme"
33+
}

test/fixtures/classic-app/input.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
module.exports = {
2+
app: {
3+
'app.js': '// app',
4+
components: {
5+
'top-level-component.js': '// top-level-component.js',
6+
nested1: {
7+
'nested-component.js': '// nested1/nested-component.js',
8+
nested2: {
9+
'super-nested-component.js': '// nested1/nested2/super-nested-component.js',
10+
}
11+
}
12+
},
13+
templates: {
14+
'application.hbs': '{{outlet}}',
15+
components: {
16+
'top-level-component.hbs': '{{!-- top-level-component.hbs --}}',
17+
nested1: {
18+
'nested-component.hbs': '{{!-- nested1/nested-component.hbs --}}',
19+
nested2: {
20+
'super-nested-component.hbs': '{{!-- nested1/nested2/super-nested-component.hbs --}}'
21+
}
22+
}
23+
}
24+
}
25+
},
26+
};

test/fixtures/classic-app/output.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
module.exports = {
2+
app: {
3+
'app.js': '// app',
4+
components: {
5+
'top-level-component.hbs': '{{!-- top-level-component.hbs --}}',
6+
'top-level-component.js': '// top-level-component.js',
7+
nested1: {
8+
'nested-component.hbs': '{{!-- nested1/nested-component.hbs --}}',
9+
'nested-component.js': '// nested1/nested-component.js',
10+
nested2: {
11+
'super-nested-component.hbs': '{{!-- nested1/nested2/super-nested-component.hbs --}}',
12+
'super-nested-component.js': '// nested1/nested2/super-nested-component.js'
13+
}
14+
}
15+
},
16+
templates: {
17+
'application.hbs': '{{outlet}}',
18+
}
19+
},
20+
};

test/migrator-test.js

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// inspired by https://github.com/ember-codemods/ember-module-migrator/blob/master/test/engines/classic-test.js
2+
3+
var path = require("path");
4+
var assert = require("power-assert");
5+
var assertDiff = require('assert-diff');
6+
var fixturify = require("fixturify");
7+
var fse = require("fs-extra");
8+
var Migrator = require('../lib/migrator');
9+
10+
assertDiff.options.strict = true;
11+
12+
describe("Migrator", function() {
13+
var tmpPath = "tmp/process-files";
14+
var fixturesPath = path.resolve(__dirname, "fixtures");
15+
16+
beforeEach(function() {
17+
fse.mkdirsSync(tmpPath);
18+
});
19+
20+
afterEach(function() {
21+
fse.removeSync(tmpPath);
22+
});
23+
24+
var entries = fse.readdirSync(fixturesPath);
25+
26+
entries.forEach(async function(entry) {
27+
it(`should migrate ${entry} fixture properly`, async function() {
28+
var fixturePath = path.join(fixturesPath, entry);
29+
var input = require(fixturePath + "/input");
30+
var expected = require(fixturePath + "/output");
31+
var migratorConfig = {};
32+
try {
33+
migratorConfig = require(fixturePath + "/config");
34+
} catch (e) {
35+
// fixture uses default config...
36+
}
37+
38+
fixturify.writeSync(tmpPath, input);
39+
40+
var migratorOptions = Object.assign(
41+
{ projectRoot: tmpPath },
42+
migratorConfig
43+
);
44+
45+
var migrator = new Migrator(migratorOptions);
46+
await migrator.execute();
47+
48+
var actual = fixturify.readSync(tmpPath);
49+
assertDiff.deepEqual(actual, expected, "the codemod should work as expected");
50+
51+
await migrator.execute();
52+
assertDiff.deepEqual(actual, expected, "the codemod should be idempotent");
53+
});
54+
});
55+
});
56+

0 commit comments

Comments
 (0)