Skip to content

Commit 14c42a7

Browse files
author
Josh Goldberg
authored
Allowed custom .js or .json file outputs with --config (#75)
As before, the output path defaults to `--eslintrc.js`. `--eslint` will default to `--config` which has that default. The format of the output path depends on its file extension, with JavaScript for `.js` files and JSON otherwise. The README.md list of flags is getting a little long so I added a quick manual table of contents. Will try to remember to split that into a separate PR...
1 parent b0a76e0 commit 14c42a7

15 files changed

+193
-62
lines changed

README.md

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,19 +36,35 @@ TSLint rules without ESLint equivalents will be wrapped with [eslint-plugin-tsli
3636

3737
Each of these flags is optional.
3838

39+
- **[`config`](#config)**: Path to print the generated ESLint configuration file to.
3940
- **[`eslint`](#eslint)**: Path to an ESLint configuration file to read settings from.
4041
- **[`package`](#package)**: Path to a package.json file to read dependencies from.
4142
- **[`tslint`](#tslint)**: Path to a TSLint configuration file to read settings from.
4243
- **[`typescript`](#typescript)**: Path to a TypeScript configuration file to read TypeScript compiler options from.
4344

44-
#### `eslint`
45+
#### `config`
4546

4647
```shell
47-
npx tslint-to-eslint-config --eslint ./path/to/eslintrc.json
48+
npx tslint-to-eslint-config --config .eslintrc.json
4849
```
4950

5051
_Default: `.eslintrc.js`_
5152

53+
Path to print the generated ESLint configuration file to.
54+
55+
The file extension of this path will be used to determine the format of the created file:
56+
57+
- `.js` file paths will be written `module.exports = ...` JavaScript
58+
- Other file paths will default to JSON
59+
60+
#### `eslint`
61+
62+
```shell
63+
npx tslint-to-eslint-config --eslint ./path/to/eslintrc.js
64+
```
65+
66+
_Default: `--config`'s value_
67+
5268
Path to an ESLint configuration file to read settings from.
5369
This isn't yet used for anything, but will eventually inform settings for the generated ESLint configuration file.
5470

src/cli/runCli.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,17 @@ export const runCli = async (
1919
): Promise<ResultStatus> => {
2020
const command = new Command()
2121
.usage("[options] <file ...> --language [language]")
22-
.option("--eslint [eslint]", "eslint configuration file to convert")
23-
.option("--package [package]", "package configuration file to convert")
24-
.option("--tslint [tslint]", "tslint configuration file to convert")
25-
.option("--typescript [typescript]", "typescript configuration file to convert")
22+
.option("--config [config]", "eslint configuration file to output to")
23+
.option("--eslint [eslint]", "eslint configuration file to convert using")
24+
.option("--package [package]", "package configuration file to convert using")
25+
.option("--tslint [tslint]", "tslint configuration file to convert using")
26+
.option("--typescript [typescript]", "typescript configuration file to convert using")
2627
.option("-V --version", "output the package version");
2728

28-
const parsedArgv = command.parse(rawArgv) as Partial<TSLintToESLintSettings>;
29+
const parsedArgv = {
30+
config: "./eslintrc.js",
31+
...(command.parse(rawArgv) as Partial<TSLintToESLintSettings>),
32+
};
2933

3034
if ({}.hasOwnProperty.call(parsedArgv, "version")) {
3135
dependencies.logger.stdout.write(`${version}${EOL}`);

src/conversion/convertConfig.test.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@ describe("convertConfig", () => {
2828
const dependencies = createStubDependencies({
2929
findOriginalConfigurations: async () => findError,
3030
});
31-
const settings = {};
31+
const settings = {
32+
config: "./eslintrc.js",
33+
};
3234

3335
// Act
3436
const result = await convertConfig(dependencies, settings);
@@ -46,7 +48,9 @@ describe("convertConfig", () => {
4648
const dependencies = createStubDependencies({
4749
findOriginalConfigurations: async () => findSuccess,
4850
});
49-
const settings = {};
51+
const settings = {
52+
config: "./eslintrc.js",
53+
};
5054

5155
// Act
5256
const result = await convertConfig(dependencies, settings);

src/conversion/convertConfig.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,11 @@ export const convertConfig = async (
2525
originalConfigurations.data.tslint.rules,
2626
);
2727

28-
await dependencies.writeConversionResults(ruleConversionResults, originalConfigurations.data);
28+
await dependencies.writeConversionResults(
29+
settings.config,
30+
ruleConversionResults,
31+
originalConfigurations.data,
32+
);
2933
dependencies.reportConversionResults(ruleConversionResults);
3034

3135
return {
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import { EOL } from "os";
2+
3+
import { formatOutput } from "./formatOutput";
4+
5+
describe("formatOutput", () => {
6+
it("formats output as JavaScript for a .js file path", () => {
7+
// Arrange
8+
const outputPath = ".eslintrc.js";
9+
const configuration = { rules: {} };
10+
11+
// Act
12+
const output = formatOutput(outputPath, configuration);
13+
14+
// Assert
15+
expect(output).toBe(
16+
`module.exports = ${JSON.stringify(configuration, undefined, 4)};${EOL}`,
17+
);
18+
});
19+
20+
it("formats output as JSON for a .json file path", () => {
21+
// Arrange
22+
const outputPath = ".eslintrc.json";
23+
const configuration = { rules: {} };
24+
25+
// Act
26+
const output = formatOutput(outputPath, configuration);
27+
28+
// Assert
29+
expect(output).toBe(`${JSON.stringify(configuration, undefined, 4)}${EOL}`);
30+
});
31+
32+
it("formats output as JSON for an unknown dot file path", () => {
33+
// Arrange
34+
const outputPath = ".eslintrc";
35+
const configuration = { rules: {} };
36+
37+
// Act
38+
const output = formatOutput(outputPath, configuration);
39+
40+
// Assert
41+
expect(output).toBe(`${JSON.stringify(configuration, undefined, 4)}${EOL}`);
42+
});
43+
44+
it("formats output as JSON for an unknown raw file path", () => {
45+
// Arrange
46+
const outputPath = "eslintrc";
47+
const configuration = { rules: {} };
48+
49+
// Act
50+
const output = formatOutput(outputPath, configuration);
51+
52+
// Assert
53+
expect(output).toBe(`${JSON.stringify(configuration, undefined, 4)}${EOL}`);
54+
});
55+
});
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { formatJsonOutput } from "./formatters/formatJsonOutput";
2+
import { formatJsOutput } from "./formatters/formatJsOutput";
3+
4+
const formatters = new Map([["js", formatJsOutput]]);
5+
6+
export const formatOutput = (outputPath: string, configuration: unknown): string => {
7+
const customFormatter = formatters.get(getExtension(outputPath));
8+
const formatter = customFormatter === undefined ? formatJsonOutput : formatJsOutput;
9+
10+
return formatter(configuration);
11+
};
12+
13+
const getExtension = (outputPath: string) => {
14+
const periodIndex = outputPath.lastIndexOf(".");
15+
16+
return periodIndex === -1 ? outputPath : outputPath.slice(periodIndex + 1);
17+
};
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import { EOL } from "os";
2+
3+
export const formatJsOutput = (configuration: unknown) =>
4+
`module.exports = ${JSON.stringify(configuration, undefined, 4)};${EOL}`;
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import { EOL } from "os";
2+
3+
export const formatJsonOutput = (configuration: unknown) =>
4+
`${JSON.stringify(configuration, undefined, 4)}${EOL}`;
Lines changed: 47 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { createEmptyConversionResults } from "../conversion/conversionResults.stubs";
22
import { writeConversionResults } from "./writeConversionResults";
3+
import { formatJsonOutput } from "./formatting/formatters/formatJsonOutput";
34

45
const originalConfigurations = {
56
tslint: {
@@ -17,29 +18,30 @@ describe("writeConversionResults", () => {
1718
const fileSystem = { writeFile: jest.fn().mockReturnValue(Promise.resolve()) };
1819

1920
// Act
20-
await writeConversionResults({ fileSystem }, conversionResults, originalConfigurations);
21+
await writeConversionResults(
22+
{ fileSystem },
23+
".eslintrc.json",
24+
conversionResults,
25+
originalConfigurations,
26+
);
2127

2228
// Assert
2329
expect(fileSystem.writeFile).toHaveBeenLastCalledWith(
2430
".eslintrc.json",
25-
JSON.stringify(
26-
{
27-
env: {
28-
browser: true,
29-
es6: true,
30-
node: true,
31-
},
32-
parser: "@typescript-eslint/parser",
33-
parserOptions: {
34-
project: "tsconfig.json",
35-
sourceType: "module",
36-
},
37-
plugins: ["@typescript-eslint"],
38-
rules: {},
31+
formatJsonOutput({
32+
env: {
33+
browser: true,
34+
es6: true,
35+
node: true,
3936
},
40-
undefined,
41-
4,
42-
),
37+
parser: "@typescript-eslint/parser",
38+
parserOptions: {
39+
project: "tsconfig.json",
40+
sourceType: "module",
41+
},
42+
plugins: ["@typescript-eslint"],
43+
rules: {},
44+
}),
4345
);
4446
});
4547

@@ -58,38 +60,39 @@ describe("writeConversionResults", () => {
5860
const fileSystem = { writeFile: jest.fn().mockReturnValue(Promise.resolve()) };
5961

6062
// Act
61-
await writeConversionResults({ fileSystem }, conversionResults, originalConfigurations);
63+
await writeConversionResults(
64+
{ fileSystem },
65+
".eslintrc.json",
66+
conversionResults,
67+
originalConfigurations,
68+
);
6269

6370
// Assert
6471
expect(fileSystem.writeFile).toHaveBeenLastCalledWith(
6572
".eslintrc.json",
66-
JSON.stringify(
67-
{
68-
env: {
69-
browser: true,
70-
es6: true,
71-
node: true,
72-
},
73-
parser: "@typescript-eslint/parser",
74-
parserOptions: {
75-
project: "tsconfig.json",
76-
sourceType: "module",
77-
},
78-
plugins: ["@typescript-eslint", "@typescript-eslint/tslint"],
79-
rules: {
80-
"@typescript-eslint/tslint/config": [
81-
"error",
82-
{
83-
rules: {
84-
"tslint-rule-one": true,
85-
},
73+
formatJsonOutput({
74+
env: {
75+
browser: true,
76+
es6: true,
77+
node: true,
78+
},
79+
parser: "@typescript-eslint/parser",
80+
parserOptions: {
81+
project: "tsconfig.json",
82+
sourceType: "module",
83+
},
84+
plugins: ["@typescript-eslint", "@typescript-eslint/tslint"],
85+
rules: {
86+
"@typescript-eslint/tslint/config": [
87+
"error",
88+
{
89+
rules: {
90+
"tslint-rule-one": true,
8691
},
87-
],
88-
},
92+
},
93+
],
8994
},
90-
undefined,
91-
4,
92-
),
95+
}),
9396
);
9497
});
9598
});

src/creation/writeConversionResults.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@ import { RuleConversionResults } from "../rules/convertRules";
33
import { formatConvertedRules } from "./formatConvertedRules";
44
import { OriginalConfigurations } from "../input/findOriginalConfigurations";
55
import { createEnv } from "./eslint/createEnv";
6+
import { formatOutput } from "./formatting/formatOutput";
67

78
export type WriteConversionResultsDependencies = {
89
fileSystem: Pick<FileSystem, "writeFile">;
910
};
1011

1112
export const writeConversionResults = async (
1213
dependencies: WriteConversionResultsDependencies,
14+
outputPath: string,
1315
ruleConversionResults: RuleConversionResults,
1416
originalConfigurations: OriginalConfigurations,
1517
) => {
@@ -29,5 +31,5 @@ export const writeConversionResults = async (
2931
rules: formatConvertedRules(ruleConversionResults, originalConfigurations.tslint),
3032
};
3133

32-
await dependencies.fileSystem.writeFile(".eslintrc.json", JSON.stringify(output, undefined, 4));
34+
await dependencies.fileSystem.writeFile(outputPath, formatOutput(outputPath, output));
3335
};

0 commit comments

Comments
 (0)