diff --git a/README.md b/README.md index 39c01be..a2e4ce7 100644 --- a/README.md +++ b/README.md @@ -181,6 +181,8 @@ more information. extensionless files), but this mapping can be used to override the behavior to provide a specific target directory, name, and/or file extension for any specific files being converted. +* `outputFileExtension`: an optional file extension, like `"ts"` or `"jsx"`. If + specified, all converted files will have this extension. * `jscodeshiftScripts`: an optional array of paths to [jscodeshift](https://github.com/facebook/jscodeshift) scripts to run after decaffeinate. This is useful to automate any cleanups to convert the output of diff --git a/src/config/resolveConfig.js b/src/config/resolveConfig.js index 527a2ee..5832bec 100644 --- a/src/config/resolveConfig.js +++ b/src/config/resolveConfig.js @@ -27,6 +27,7 @@ export default async function resolveConfig(commander) { searchDirectory: config.searchDirectory, fileFilterFn: config.fileFilterFn, customNames: resolveCustomNames(config.customNames), + outputFileExtension: config.outputFileExtension || 'js', fixImportsConfig: config.fixImportsConfig, jscodeshiftScripts: config.jscodeshiftScripts, landConfig: config.landConfig, diff --git a/src/convert.js b/src/convert.js index 19b2699..5c86fd0 100644 --- a/src/convert.js +++ b/src/convert.js @@ -48,7 +48,7 @@ Re-run with the "check" command for more details.`); }); await runWithProgressBar( - 'Renaming files from .coffee to .js...', + `Renaming files from .coffee to .${config.outputFileExtension}...`, movingCoffeeFiles, async function(coffeePath) { await move(coffeePath, jsPathFor(coffeePath, config)); @@ -56,7 +56,7 @@ Re-run with the "check" command for more details.`); let shortDescription = getShortDescription(coffeeFiles); let renameCommitMsg = - `decaffeinate: Rename ${shortDescription} from .coffee to .js`; + `decaffeinate: Rename ${shortDescription} from .coffee to .${config.outputFileExtension}`; if (movingCoffeeFiles.length > 0) { console.log(`Generating the first commit: "${renameCommitMsg}"...`); diff --git a/src/util/FilePaths.js b/src/util/FilePaths.js index d1d114e..4a890df 100644 --- a/src/util/FilePaths.js +++ b/src/util/FilePaths.js @@ -53,7 +53,7 @@ export function jsPathFor(path, config) { if (isExtensionless(path)) { return path; } else { - return basePathFor(path) + '.js'; + return basePathFor(path) + '.' + config.outputFileExtension; } } diff --git a/test/convert-test.js b/test/convert-test.js index dd97e24..71a5f45 100644 --- a/test/convert-test.js +++ b/test/convert-test.js @@ -339,6 +339,14 @@ console.log(x); }); }); + it('allows a custom file extension', async function() { + await runWithTemplateDir('convert-to-typescript', async function() { + await initGitRepo(); + await runCli('convert'); + await assertExists('./A.ts'); + }); + }); + it('handles a missing eslint config', async function() { await runWithTemplateDir('simple-success', async function() { await initGitRepo(); diff --git a/test/examples/convert-to-typescript/A.coffee b/test/examples/convert-to-typescript/A.coffee new file mode 100644 index 0000000..e62fe84 --- /dev/null +++ b/test/examples/convert-to-typescript/A.coffee @@ -0,0 +1 @@ +console.log 'This is a file' diff --git a/test/examples/convert-to-typescript/bulk-decaffeinate.config.js b/test/examples/convert-to-typescript/bulk-decaffeinate.config.js new file mode 100644 index 0000000..545fed6 --- /dev/null +++ b/test/examples/convert-to-typescript/bulk-decaffeinate.config.js @@ -0,0 +1,3 @@ +module.exports = { + outputFileExtension: 'ts', +}; diff --git a/test/util/FilePaths-test.js b/test/util/FilePaths-test.js index fa18022..5edd21b 100644 --- a/test/util/FilePaths-test.js +++ b/test/util/FilePaths-test.js @@ -12,13 +12,17 @@ describe('FilePaths', () => { }); it('generates correct js paths', () => { - let emptyConfig = {customNames: {}}; + let emptyConfig = {customNames: {}, outputFileExtension: 'js'}; assert.equal(FilePaths.jsPathFor('./a/b/foo.coffee', emptyConfig), 'a/b/foo.js'); assert.equal(FilePaths.jsPathFor('foo.coffee', emptyConfig), 'foo.js'); assert.equal(FilePaths.jsPathFor('foo.coffee.md', emptyConfig), 'foo.js'); assert.equal(FilePaths.jsPathFor('foo.cjsx', emptyConfig), 'foo.js'); assert.equal(FilePaths.jsPathFor('foo', emptyConfig), 'foo'); - assert.equal(FilePaths.jsPathFor('foo', {customNames: {foo: 'bar'}}), 'bar'); + assert.equal( + FilePaths.jsPathFor('foo', {customNames: {foo: 'bar'}}), 'bar'); + assert.equal( + FilePaths.jsPathFor('foo.coffee', {customNames: {}, outputFileExtension: 'ts'}), + 'foo.ts'); }); it('generates correct decaffeinate out paths', () => {