Skip to content

Commit 226f20c

Browse files
authored
feat: support fix and check commands (#3)
1 parent 14d2907 commit 226f20c

24 files changed

+2155
-101
lines changed

.babelrc

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"presets": [["env", { "targets": { "node": "4.5" } }]]
3+
}

.eslintrc.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
"es6": true
77
},
88
"globals": {
9-
"process": true
9+
"process": true,
10+
"console": true
1011
},
1112
"rules": {
1213
"curly": ["error"],

.gitignore

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
11
node_modules
2-
.esm-cache
3-
.vscode
2+
dist
43
*.log

.travis.yml

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ install:
1515
- yarn
1616
script:
1717
- yarn lint
18+
- yarn build
1819
- yarn test
1920
after_success:
2021
- npm run semantic-release

README.md

+17-7
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ Or with `yarn`:
2525
yarn add --dev prettier-tslint
2626
```
2727

28-
## Confituration
28+
## Configuration
2929

3030
`prettier-tslint` find and will respect:
3131

@@ -37,17 +37,27 @@ yarn add --dev prettier-tslint
3737

3838
## CLI
3939

40-
```bash
41-
pretttier-tslint file.ts
40+
```
41+
Commands:
42+
fix Fix one or more files
43+
check List files that aren't formatted
44+
45+
Options:
46+
--version Show version number [boolean]
47+
--help Show help [boolean]
48+
49+
Examples:
50+
prettier-tslint fix file1.ts file2.ts Fix provided files
51+
prettier-tslint fix '**/*.ts' Fix all TypeScript files
52+
prettier-tslint check '**/*.ts' List all unformatted TypeScript files
4253
```
4354

4455
## API
4556

46-
4757
```js
48-
import format from "prettier-eslint";
58+
import { fix } from "prettier-tslint";
4959

50-
format("file.ts");
60+
fix("file.ts");
5161
```
5262

53-
Currently the `format` function will write to disk and not return anything. This behavior **will change** in a minor release before `1.0.0` is released.
63+
Currently the `fix` function will write to disk and not return anything. This behavior **will change** in a minor release before `1.0.0` is released.

__mocks__/.eslintrc.json

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"env": {
3+
"jest": true
4+
}
5+
}

__mocks__/fs.js

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import path from "path";
2+
3+
const actual = require.requireActual("fs");
4+
5+
let writes = {};
6+
7+
export const statSync = jest.fn(actual.statSync);
8+
export const existsSync = jest.fn(actual.existsSync);
9+
10+
export const writeFileSync = jest.fn((filePath, content) => {
11+
const relative = path.relative(process.cwd(), filePath);
12+
writes[relative] = content;
13+
});
14+
15+
export const readFileSync = jest.fn(filePath => {
16+
const relative = path.relative(process.cwd(), filePath);
17+
if (writes[relative]) {
18+
return writes[relative];
19+
}
20+
return actual.readFileSync(filePath, "utf8");
21+
});
22+
23+
export const __clear = () => {
24+
writes = {};
25+
existsSync.mockClear();
26+
statSync.mockClear();
27+
writeFileSync.mockClear();
28+
readFileSync.mockClear();
29+
};
30+
31+
export default {
32+
__clear,
33+
existsSync,
34+
statSync,
35+
readFileSync,
36+
writeFileSync,
37+
};

index.js

-4
This file was deleted.

package.json

+10-6
Original file line numberDiff line numberDiff line change
@@ -4,34 +4,38 @@
44
"version": "0.0.0-development",
55
"author": "Lucas Azzola <@azz>",
66
"license": "MIT",
7+
"main": "dist",
78
"bin": "./bin/prettier-tslint.js",
89
"files": [
910
"bin",
10-
"src",
11-
"index.js"
11+
"dist"
1212
],
1313
"dependencies": {
14-
"@std/esm": "^0.11.3",
14+
"chalk": "^2.2.0",
1515
"globby": "^6.1.0",
1616
"ignore": "^3.3.5",
17-
"minimist": "^1.2.0",
18-
"tslint": "^5.7.0"
17+
"tslint": "^5.7.0",
18+
"yargs": "^9.0.1"
1919
},
2020
"peerDependencies": {
2121
"prettier": "^1.7.4",
2222
"typescript": "^2.5.3"
2323
},
2424
"devDependencies": {
25+
"babel-cli": "^6.26.0",
26+
"babel-preset-env": "^1.6.1",
2527
"eslint": "^4.9.0",
2628
"eslint-config-prettier": "^2.6.0",
2729
"eslint-plugin-prettier": "^2.3.1",
30+
"jest": "^21.2.1",
2831
"prettier": "1.7.4",
2932
"semantic-release": "^8.0.3",
3033
"typescript": "~2.5.3"
3134
},
3235
"scripts": {
3336
"lint": "eslint .",
34-
"test": "echo soon...",
37+
"test": "jest",
38+
"build": "babel --copy-files --out-dir dist src",
3539
"semantic-release": "semantic-release pre && npm publish && semantic-release post"
3640
},
3741
"repository": {

src/check.js

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import runTsLint from "./run-tslint";
2+
import runPrettier from "./run-prettier";
3+
4+
const check = filePath => {
5+
return runPrettier(filePath, false) && runTsLint(filePath, false);
6+
};
7+
8+
export default check;

src/cli.js

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/* eslint no-console: 0 */
2+
3+
import chalk from "chalk";
4+
import yargs from "yargs";
5+
6+
import fix from "./fix";
7+
import check from "./check";
8+
import expandGlob from "./expand-glob";
9+
import filterIgnored from "./filter-ignored";
10+
11+
const cli = argv => {
12+
const yargsInstance = yargs
13+
// Fix
14+
.command("fix", "Fix one or more files")
15+
.example("prettier-tslint fix file1.ts file2.ts", "Fix provided files")
16+
.example("prettier-tslint fix '**/*.ts'", "Fix all .ts files")
17+
// Check
18+
.command("check", "List files that aren't formatted")
19+
.example("prettier-tslint check '**/*.ts'", "List unformatted .ts files")
20+
// Meta
21+
.demandCommand(1, "Command not provided.")
22+
.help();
23+
24+
const args = yargsInstance.parse(argv);
25+
const command = args._[0];
26+
const patterns = args._.slice(1);
27+
28+
switch (command) {
29+
case "fix":
30+
return patterns.forEach(fixFiles);
31+
case "check":
32+
return patterns.forEach(checkFiles);
33+
default:
34+
yargs.showHelp();
35+
console.error(`Unknown command: ${command}`);
36+
}
37+
};
38+
39+
const fixFiles = filePattern => {
40+
const files = filterIgnored(expandGlob(filePattern));
41+
files.forEach(file => {
42+
const changed = !fix(file);
43+
console.log(changed ? file : chalk.gray(file));
44+
});
45+
};
46+
47+
const checkFiles = filePattern => {
48+
const files = filterIgnored(expandGlob(filePattern));
49+
const invalid = files.filter(file => !check(file));
50+
if (invalid.length) {
51+
process.exitCode = 1;
52+
}
53+
invalid.forEach(file => console.error(chalk.red.bold(file)));
54+
};
55+
56+
export default cli;

src/expand-glob.js

+6-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
import globby from "globby";
22

33
const expandGlob = glob => {
4-
return globby.sync(glob, {
5-
dot: true,
6-
});
4+
return globby.sync(
5+
[glob].concat(["!**/node_modules/**", "!./node_modules/**"]),
6+
{
7+
dot: true,
8+
}
9+
);
710
};
811

912
export default expandGlob;

src/fix.js

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import runTsLint from "./run-tslint";
2+
import runPrettier from "./run-prettier";
3+
4+
const fix = filePath => {
5+
const prettierCheck = runPrettier(filePath, true);
6+
const tslintCheck = runTsLint(filePath, true);
7+
return prettierCheck && tslintCheck;
8+
};
9+
10+
export default fix;

src/index.js

+3-24
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,5 @@
11
import fs from "fs";
2-
import minimist from "minimist";
32

4-
import expandGlob from "./expand-glob";
5-
import filterIgnored from "./filter-ignored";
6-
import runTsLint from "./run-tslint";
7-
import runPrettier from "./run-prettier";
8-
9-
const format = filePath => {
10-
runPrettier(filePath);
11-
runTsLint(filePath);
12-
};
13-
14-
const formatFiles = filePattern => {
15-
const files = filterIgnored(expandGlob(filePattern));
16-
files.forEach(format);
17-
};
18-
19-
const cliOpts = {};
20-
21-
export const cli = argv => {
22-
const args = minimist(argv, cliOpts);
23-
args._.forEach(formatFiles);
24-
};
25-
26-
export default format;
3+
export { default as cli } from "./cli";
4+
export { default as fix } from "./fix";
5+
export { default as check } from "./check";

src/run-prettier.js

+16-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,24 @@
11
import fs from "fs";
22
import prettier from "prettier";
33

4-
const runPrettier = filepath => {
4+
/**
5+
* @returns true iff output === input
6+
*/
7+
const runPrettier = (filepath, fix) => {
58
const config = prettier.resolveConfig.sync(filepath);
69
const code = fs.readFileSync(filepath, "utf8");
7-
const output = prettier.format(code, Object.assign({ filepath }, config));
8-
fs.writeFileSync(filepath, output);
10+
const options = Object.assign({ filepath }, config);
11+
12+
if (fix) {
13+
const output = prettier.format(code, options);
14+
if (output !== code) {
15+
fs.writeFileSync(filepath, output);
16+
return false;
17+
}
18+
return true;
19+
} else {
20+
return prettier.check(code, options);
21+
}
922
};
1023

1124
export default runPrettier;

src/run-tslint.js

+13-4
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,28 @@
11
import fs from "fs";
2-
import tslint from "tslint";
2+
import * as tslint from "tslint";
33
import createProgram from "./create-program";
44

5-
const runTsLint = filepath => {
5+
/**
6+
* @returns true iff output === input
7+
*/
8+
const runTsLint = (filepath, fix) => {
69
const code = fs.readFileSync(filepath, "utf8");
710
const config = tslint.Configuration.findConfiguration(null, filepath).results;
811

912
const program = createProgram(filepath);
1013

1114
// TODO(azz): This actually writes over the file, we don't really want that...
12-
const linter = new tslint.Linter({ fix: true }, program);
15+
const linter = new tslint.Linter({ fix }, program);
1316

1417
linter.lint(filepath, code, config);
1518
const result = linter.getResult();
16-
return result;
19+
if (fix) {
20+
// There were no fixes applied
21+
return result.fixes.length === 0;
22+
} else {
23+
// There were no auto-fixable problems
24+
return !result.failures.find(failure => failure.fix);
25+
}
1726
};
1827

1928
export default runTsLint;

test/.eslintrc.json

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"env": {
3+
"jest": true
4+
}
5+
}

test/__snapshots__/fix.test.js.snap

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`fix() bad format, bad lint writes fix to disk 1`] = `
4+
Array [
5+
"test/fixture/bad-format-bad-lint.ts",
6+
"throw new Error(\\"no-string-throw\\");
7+
",
8+
]
9+
`;
10+
11+
exports[`fix() bad format, good lint writes fix to disk 1`] = `
12+
Array [
13+
"test/fixture/bad-format-good-lint.ts",
14+
"throw new Error(\\"no-string-throw\\");
15+
",
16+
]
17+
`;
18+
19+
exports[`fix() good format, bad lint writes fix to disk 1`] = `
20+
Array [
21+
"test/fixture/good-format-bad-lint.ts",
22+
"throw new Error(\\"no-string-throw\\");
23+
",
24+
]
25+
`;

test/check.test.js

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import check from "../src/check";
2+
3+
describe("check()", () => {
4+
test("good format, bad lint fails check", () => {
5+
expect(check("test/fixture/good-format-bad-lint.ts")).toEqual(false);
6+
});
7+
test("bad format, good lint fails check", () => {
8+
expect(check("test/fixture/bad-format-good-lint.ts")).toEqual(false);
9+
});
10+
test("bad format, bad lint fails check", () => {
11+
expect(check("test/fixture/bad-format-bad-lint.ts")).toEqual(false);
12+
});
13+
test("good format, good lint passes check", () => {
14+
expect(check("test/fixture/good-format-good-lint.ts")).toEqual(true);
15+
});
16+
});

0 commit comments

Comments
 (0)