forked from lyft/react-javascript-to-typescript-transform
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcli.ts
98 lines (93 loc) · 3.99 KB
/
cli.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#!/usr/bin/env node
import * as program from 'commander';
import * as glob from 'glob';
import * as fs from 'fs';
import * as path from 'path';
import * as prettier from 'prettier';
import { run } from '.';
import { CompilationOptions } from './compiler';
function resolveGlobs(globPatterns: string[]): string[] {
const files: string[] = [];
function addFile(file: string) {
file = path.resolve(file);
if (files.indexOf(file) === -1) {
files.push(file);
}
}
globPatterns.forEach(pattern => {
if (/[{}*?+\[\]]/.test(pattern)) {
// Smells like globs
glob.sync(pattern, {}).forEach(file => {
addFile(file);
});
} else {
addFile(pattern);
}
});
return files;
}
program
.version('1.0.0')
.option('--arrow-parens <avoid|always>', 'Include parentheses around a sole arrow function parameter.', 'avoid')
.option('--no-bracket-spacing', 'Do not print spaces between brackets.', false)
.option('--jsx-bracket-same-line', 'Put > on the last line instead of at a new line.', false)
.option('--print-width <int>', 'The line length where Prettier will try wrap.', 80)
.option('--prose-wrap <always|never|preserve> How to wrap prose. (markdown)', 'preserve')
.option('--no-semi', 'Do not print semicolons, except at the beginning of lines which may need them', false)
.option('--single-quote', 'Use single quotes instead of double quotes.', false)
.option('--tab-width <int>', 'Number of spaces per indentation level.', 2)
.option('--trailing-comma <none|es5|all>', 'Print trailing commas wherever possible when multi-line.', 'none')
.option('--use-tabs', 'Indent with tabs instead of spaces.', false)
.option('--ignore-prettier-errors', 'Ignore (but warn about) errors in Prettier', false)
.option('--keep-original-files', 'Keep original files', false)
.option('--keep-temporary-files', 'Keep temporary files', false)
.usage('[options] <filename or glob>')
.command('* [glob/filename...]')
.action((globPatterns: string[]) => {
const prettierOptions: prettier.Options = {
arrowParens: program.arrowParens,
bracketSpacing: !program.noBracketSpacing,
jsxBracketSameLine: !!program.jsxBracketSameLine,
printWidth: parseInt(program.printWidth, 10),
proseWrap: program.proseWrap,
semi: !program.noSemi,
singleQuote: !!program.singleQuote,
tabWidth: parseInt(program.tabWidth, 10),
trailingComma: program.trailingComma,
useTabs: !!program.useTabs,
};
const compilationOptions: CompilationOptions = {
ignorePrettierErrors: !!program.ignorePrettierErrors,
};
const files = resolveGlobs(globPatterns);
if (!files.length) {
throw new Error('Nothing to do. You must provide file names or glob patterns to transform.');
}
let errors = false;
for (const filePath of files) {
console.log(`Transforming ${filePath}...`);
const newPath = filePath.replace(/\.jsx?$/, '.tsx');
const temporaryPath = filePath.replace(/\.jsx?$/, `_js2ts_${+new Date()}.tsx`);
try {
fs.copyFileSync(filePath, temporaryPath);
const result = run(temporaryPath, prettierOptions, compilationOptions);
fs.writeFileSync(newPath, result);
if (!program.keepOriginalFiles) {
fs.unlinkSync(filePath);
}
} catch (error) {
console.warn(`Failed to convert ${filePath}`);
console.warn(error);
errors = true;
}
if (!program.keepTemporaryFiles) {
if (fs.existsSync(temporaryPath)) {
fs.unlinkSync(temporaryPath);
}
}
}
if (errors) {
process.exit(1);
}
});
program.parse(process.argv);