Skip to content

Commit b978f7f

Browse files
committed
Merge branch 'master' into ignore-options-support
2 parents bff35ab + 1e08083 commit b978f7f

11 files changed

Lines changed: 605 additions & 37 deletions

File tree

commands/local/generate/codemod.js

Lines changed: 106 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,19 @@ module.exports.command = 'codemod <codemod-name>';
22
module.exports.desc = 'Generate a new codemod file';
33

44
module.exports.builder = function builder(yargs) {
5-
yargs.positional('codemod-name', {
6-
describe: 'the name of the codemod to generate',
7-
});
5+
yargs
6+
.positional('codemod-name', {
7+
describe: 'the name of the codemod to generate',
8+
})
9+
.option('type', {
10+
alias: 't',
11+
describe: 'choose the transform type',
12+
choices: ['js', 'hbs'],
13+
default: 'js',
14+
});
815
};
916

10-
module.exports.handler = function handler(options) {
17+
function jsHandler(options) {
1118
const fs = require('fs-extra');
1219
const { stripIndent } = require('common-tags');
1320
const importCwd = require('import-cwd');
@@ -36,7 +43,9 @@ module.exports.handler = function handler(options) {
3643
.join('');
3744
})
3845
.toSource();
39-
}
46+
};
47+
48+
module.exports.type = 'js';
4049
`,
4150
'utf8'
4251
);
@@ -47,8 +56,7 @@ module.exports.handler = function handler(options) {
4756
4857
const { runTransformTest } = require('codemod-cli');
4958
50-
runTransformTest({
51-
type: 'jscodeshift',
59+
runTransformTest({
5260
name: '${codemodName}',
5361
});
5462
`,
@@ -86,5 +94,95 @@ module.exports.handler = function handler(options) {
8694
'utf8'
8795
);
8896

89-
generateFixture({ codemodName, fixtureName: 'basic' });
97+
generateFixture({ codemodName, fixtureName: 'basic', type: options.type });
98+
}
99+
100+
function hbsHandler(options) {
101+
const fs = require('fs-extra');
102+
const { stripIndent } = require('common-tags');
103+
const importCwd = require('import-cwd');
104+
const generateFixture = require('./fixture').handler;
105+
106+
let { codemodName } = options;
107+
let projectName = importCwd('./package.json').name;
108+
let codemodDir = `${process.cwd()}/transforms/${codemodName}`;
109+
110+
fs.outputFileSync(
111+
`${codemodDir}/index.js`,
112+
stripIndent`
113+
module.exports = function ({ source /*, path*/ }, { parse, visit }) {
114+
const ast = parse(source);
115+
116+
return visit(ast, (env) => {
117+
let { builders: b } = env.syntax;
118+
119+
return {
120+
MustacheStatement() {
121+
return b.mustache(b.path('wat-wat'));
122+
},
123+
};
124+
});
125+
};
126+
127+
module.exports.type = 'hbs';
128+
`,
129+
'utf8'
130+
);
131+
fs.outputFileSync(
132+
`${codemodDir}/test.js`,
133+
stripIndent`
134+
'use strict';
135+
136+
const { runTransformTest } = require('codemod-cli');
137+
138+
runTransformTest({
139+
name: '${codemodName}',
140+
});
141+
`,
142+
'utf8'
143+
);
144+
fs.outputFileSync(
145+
`${codemodDir}/README.md`,
146+
stripIndent`
147+
# ${codemodName}\n
148+
149+
## Usage
150+
151+
\`\`\`
152+
npx ${projectName} ${codemodName} path/of/files/ or/some**/*glob.hbs
153+
154+
# or
155+
156+
yarn global add ${projectName}
157+
${projectName} ${codemodName} path/of/files/ or/some**/*glob.hbs
158+
\`\`\`
159+
160+
## Local Usage
161+
\`\`\`
162+
node ./bin/cli.js ${codemodName} path/of/files/ or/some**/*glob.hbs
163+
\`\`\`
164+
165+
## Input / Output
166+
167+
<!--FIXTURES_TOC_START-->
168+
<!--FIXTURES_TOC_END-->
169+
170+
<!--FIXTURES_CONTENT_START-->
171+
<!--FIXTURES_CONTENT_END-->
172+
`,
173+
'utf8'
174+
);
175+
176+
generateFixture({ codemodName, fixtureName: 'basic', type: options.type });
177+
}
178+
179+
module.exports.handler = function handler(options) {
180+
switch (options.type) {
181+
case 'js':
182+
return jsHandler(options);
183+
case 'hbs':
184+
return hbsHandler(options);
185+
default:
186+
throw new Error(`Unknown type: "${options.type}"`);
187+
}
90188
};

commands/local/generate/fixture.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,14 @@ module.exports.builder = function builder(yargs) {
1313

1414
module.exports.handler = function handler(options) {
1515
const fs = require('fs-extra');
16+
const { getTransformType } = require('../../../src/transform-support');
1617

1718
let { codemodName, fixtureName } = options;
1819
let codemodDir = `${process.cwd()}/transforms/${codemodName}`;
1920
let fixturePath = `${codemodDir}/__testfixtures__/${fixtureName}`;
2021

21-
fs.outputFileSync(`${fixturePath}.input.js`, '');
22-
fs.outputFileSync(`${fixturePath}.output.js`, '');
22+
let transformType = getTransformType(codemodDir);
23+
24+
fs.outputFileSync(`${fixturePath}.input.${transformType}`, '');
25+
fs.outputFileSync(`${fixturePath}.output.${transformType}`, '');
2326
};

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
"@babel/parser": "^7.6.0",
3939
"chalk": "^2.4.2",
4040
"common-tags": "^1.8.0",
41+
"ember-template-recast": "^4.1.4",
4142
"execa": "^2.0.4",
4243
"fs-extra": "^8.1.0",
4344
"globby": "^10.0.1",

src/bin-support.js

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,22 @@
11
'use strict';
22

3-
const DEFAULT_EXTENSIONS = 'js,ts';
3+
const DEFAULT_JS_EXTENSIONS = 'js,ts';
44

5-
async function runTransform(binRoot, transformName, args, extensions = DEFAULT_EXTENSIONS) {
5+
async function runJsTransform(root, transformName, args, extensions = DEFAULT_JS_EXTENSIONS) {
66
const globby = require('globby');
77
const execa = require('execa');
88
const chalk = require('chalk');
99
const path = require('path');
1010
const { parseTransformArgs } = require('./options-support');
11+
const { getTransformPath } = require('./transform-support');
1112

1213
let { paths, options, transformerOptions } = parseTransformArgs(args);
1314

1415
try {
1516
let foundPaths = await globby(paths, {
1617
expandDirectories: { extensions: extensions.split(',') },
1718
});
18-
let transformPath = path.join(binRoot, '..', 'transforms', transformName, 'index.js');
19+
let transformPath = getTransformPath(root, transformName);
1920

2021
let jscodeshiftPkg = require('jscodeshift/package');
2122
let jscodeshiftPath = path.dirname(require.resolve('jscodeshift/package'));
@@ -44,6 +45,51 @@ async function runTransform(binRoot, transformName, args, extensions = DEFAULT_E
4445
}
4546
}
4647

48+
async function runTemplateTransform(root, transformName, args) {
49+
const execa = require('execa');
50+
const chalk = require('chalk');
51+
const { parseTransformArgs } = require('./options-support');
52+
const { getTransformPath } = require('./transform-support');
53+
54+
let { paths, options } = parseTransformArgs(args);
55+
56+
try {
57+
let transformPath = getTransformPath(root, transformName);
58+
let binOptions = ['-t', transformPath, ...paths];
59+
60+
return execa('ember-template-recast', binOptions, {
61+
stdio: 'inherit',
62+
preferLocal: true,
63+
env: {
64+
CODEMOD_CLI_ARGS: JSON.stringify(options),
65+
},
66+
});
67+
} catch (error) {
68+
console.error(chalk.red(error.stack)); // eslint-disable-line no-console
69+
process.exitCode = 1;
70+
71+
throw error;
72+
}
73+
}
74+
75+
async function runTransform(binRoot, transformName, args, extensions) {
76+
const { getTransformType, getTransformPath } = require('./transform-support');
77+
const path = require('path');
78+
79+
let root = path.join(binRoot, '..');
80+
let transformPath = getTransformPath(root, transformName);
81+
let type = getTransformType(transformPath);
82+
83+
switch (type) {
84+
case 'js':
85+
return runJsTransform(root, transformName, args, extensions);
86+
case 'hbs':
87+
return runTemplateTransform(root, transformName, args);
88+
default:
89+
throw new Error(`Unknown type passed to runTransform: "${type}"`);
90+
}
91+
}
92+
4793
module.exports = {
4894
runTransform,
4995
};

src/test-support.js

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,12 @@
22

33
/* global it, describe, beforeEach, afterEach */
44

5-
const { runInlineTest } = require('jscodeshift/dist/testUtils');
65
const fs = require('fs-extra');
76
const path = require('path');
87
const globby = require('globby');
8+
const { transformDetails } = require('./test-support/utils');
99

10-
function transformDetails(options) {
11-
let root = process.cwd() + `/transforms/${options.name}/`;
12-
13-
return {
14-
name: options.name,
15-
root,
16-
transformPath: root + 'index',
17-
fixtureDir: root + '__testfixtures__/',
18-
};
19-
}
20-
21-
function jscodeshiftTest(options) {
10+
function testRunner(options, runTest) {
2211
let details = transformDetails(options);
2312

2413
let transform = require(details.transformPath);
@@ -49,18 +38,16 @@ function jscodeshiftTest(options) {
4938
});
5039

5140
it('transforms correctly', function() {
52-
runInlineTest(
41+
runTest(
5342
transform,
54-
{},
5543
{ path: testInputPath, source: fs.readFileSync(inputPath, 'utf8') },
5644
fs.readFileSync(outputPath, 'utf8')
5745
);
5846
});
5947

6048
it('is idempotent', function() {
61-
runInlineTest(
49+
runTest(
6250
transform,
63-
{},
6451
{ path: testInputPath, source: fs.readFileSync(outputPath, 'utf8') },
6552
fs.readFileSync(outputPath, 'utf8')
6653
);
@@ -71,9 +58,15 @@ function jscodeshiftTest(options) {
7158
}
7259

7360
function runTransformTest(options) {
74-
switch (options.type) {
75-
case 'jscodeshift':
76-
return jscodeshiftTest(options);
61+
let details = transformDetails(options);
62+
63+
switch (details.transformType) {
64+
case 'js':
65+
return testRunner(options, require('./test-support/jscodeshift'));
66+
case 'hbs':
67+
return testRunner(options, require('./test-support/template'));
68+
default:
69+
throw new Error(`Unknown type of transform: "${details.transformType}"`);
7770
}
7871
}
7972

src/test-support/jscodeshift.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
'use strict';
2+
3+
const { runInlineTest } = require('jscodeshift/dist/testUtils');
4+
5+
module.exports = function runJsTest(transform, input, expectedOutput) {
6+
return runInlineTest(transform, {}, input, expectedOutput);
7+
};

src/test-support/template.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
'use strict';
2+
3+
/* global expect */
4+
5+
const { transform, parse } = require('ember-template-recast');
6+
7+
module.exports = function runTemplateTest(plugin, { path: pluginPath, source }, expectedOutput) {
8+
const code = plugin(
9+
{
10+
path: pluginPath,
11+
source,
12+
},
13+
{
14+
parse,
15+
visit(ast, callback) {
16+
const results = transform(ast, callback);
17+
return results && results.code;
18+
},
19+
}
20+
);
21+
22+
expect(code || '').toEqual(expectedOutput);
23+
};

src/test-support/utils.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
'use strict';
2+
3+
function transformDetails(options) {
4+
const { getTransformType, getTransformPath } = require('../transform-support');
5+
const path = require('path');
6+
7+
let transformPath = getTransformPath(process.cwd(), options.name);
8+
let root = path.dirname(transformPath);
9+
let transformType = getTransformType(transformPath);
10+
11+
return {
12+
name: options.name,
13+
root,
14+
transformPath,
15+
transformType,
16+
fixtureDir: path.join(root, '__testfixtures__/'),
17+
};
18+
}
19+
20+
module.exports = {
21+
transformDetails,
22+
};

src/transform-support.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
'use strict';
22

3+
function getTransformPath(root, transformName) {
4+
const path = require('path');
5+
6+
return require.resolve(path.join(root, 'transforms', transformName));
7+
}
8+
9+
function getTransformType(transformPath) {
10+
return require(transformPath).type || 'js'; // fallback to 'js' if `type` export does not exist
11+
}
12+
313
function getJSCodeshiftParser(api) {
414
try {
515
let parser = require('recast/parsers/typescript');
@@ -19,4 +29,6 @@ module.exports = {
1929
jscodeshift: {
2030
getParser: getJSCodeshiftParser,
2131
},
32+
getTransformType,
33+
getTransformPath,
2234
};

0 commit comments

Comments
 (0)