Skip to content

Commit 959e814

Browse files
committed
feat: do the thing
1 parent 9940b19 commit 959e814

16 files changed

+3788
-4
lines changed

.babelrc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"presets": [["env", { "targets": { "node": "6.10" } }]]
3+
}

.eslintrc.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
extends:
2+
- eslint:recommended
3+
- plugin:jest/recommended
4+
- plugin:prettier/recommended
5+
env:
6+
es6: true
7+
node: true
8+
rules:
9+
no-console: off
10+
overrides:
11+
- files: "src/**/*.js"
12+
parserOptions:
13+
sourceType: module

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
node_modules
22
*.log
3+
dist

.prettierignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
package.json

.prettierrc.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
trailingComma: es5
2+
singleQuote: true

README.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,39 @@
11
# `pretty-quick`
22

33
> Get Pretty Quick
4+
5+
Runs [Prettier](https://prettier.io) on your changed files.
6+
7+
Supported source control managers:
8+
9+
* Git
10+
* _Add more_
11+
12+
## Install
13+
14+
With `yarn`:
15+
16+
```shellsession
17+
yarn add --dev pretty-quick
18+
```
19+
20+
With `npm`:
21+
22+
```shellsession
23+
npm install --save-dev pretty-quick
24+
```
25+
26+
## Usage
27+
28+
With `yarn`:
29+
30+
```shellsession
31+
yarn pretty-quick
32+
```
33+
34+
With `npm`:
35+
36+
1. Add `"pretty-quick": "pretty-quick"` to the scripts section of `package.json`.
37+
2. ```shellsession
38+
npm run pretty-quick
39+
```

bin/pretty-quick.js

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,35 @@
11
#!/usr/bin/env node
22

3-
"use strict";
3+
'use strict';
44

5-
const prettier = require('prettier');
5+
const chalk = require('chalk');
66
const mri = require('mri');
77

8+
const prettyQuick = require('..').default;
9+
810
const args = mri(process.argv.slice(2));
911

12+
prettyQuick(
13+
process.cwd(),
14+
Object.assign({}, args, {
15+
onFoundSinceRevision: (scm, revision) => {
16+
console.log(
17+
`🔍 Finding changed files since ${chalk.bold(
18+
scm
19+
)} revision ${chalk.bold(revision)}`
20+
);
21+
},
22+
onFoundChangedFiles: changedFiles => {
23+
console.log(
24+
`🎯 Found ${changedFiles.length} ${
25+
changedFiles.length === 1 ? 'file' : 'files'
26+
} changed.`
27+
);
28+
},
29+
onWriteFile: file => {
30+
console.log(`✍️ Fixing up ${chalk.bold(file)}.`);
31+
},
32+
})
33+
);
34+
35+
console.log('✅ Everything is awesome!');

package.json

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,36 @@
44
"description": "Get Pretty Quick",
55
"repository": "azz/pretty-quick",
66
"author": "Lucas Azzola <@azz>",
7+
"main": "./dist",
78
"bin": "./bin/pretty-quick",
89
"license": "MIT",
10+
"files": [
11+
"bin",
12+
"dist"
13+
],
914
"dependencies": {
15+
"chalk": "^2.3.0",
16+
"execa": "^0.8.0",
17+
"ignore": "^3.3.7",
1018
"mri": "^1.1.0"
1119
},
20+
"scripts": {
21+
"prepublishOnly": "yarn build",
22+
"build": "babel src -d dist --copy-files",
23+
"test": "jest"
24+
},
1225
"peerDependencies": {
13-
"prettier": "^1.9.2"
26+
"prettier": ">=1.8.0"
27+
},
28+
"devDependencies": {
29+
"babel-cli": "^6.26.0",
30+
"babel-core": "^6.26.0",
31+
"babel-preset-env": "^1.6.1",
32+
"eslint": "^4.15.0",
33+
"eslint-config-prettier": "^2.9.0",
34+
"eslint-plugin-jest": "^21.5.0",
35+
"eslint-plugin-prettier": "^2.4.0",
36+
"jest": "^22.0.4",
37+
"prettier": "1.9.2"
1438
}
1539
}

src/__tests__/pretty-quick.test.js

Whitespace-only changes.

src/createIgnorer.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { existsSync, readFileSync } from 'fs';
2+
import { join } from 'path';
3+
import ignore from 'ignore';
4+
5+
export default (directory, filename = '.prettierignore') => {
6+
const file = join(directory, filename);
7+
if (existsSync(file)) {
8+
const text = readFileSync(file, 'utf8');
9+
return ignore()
10+
.add(text)
11+
.createFilter();
12+
}
13+
14+
return () => true;
15+
};

src/formatFiles.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { readFileSync, writeFileSync } from 'fs';
2+
import { resolveConfig, format } from 'prettier';
3+
4+
export default (files, { config, onWriteFile }) => {
5+
for (const file of files) {
6+
const options = resolveConfig.sync(file, { config });
7+
const input = readFileSync(file, 'utf8');
8+
const output = format(
9+
input,
10+
Object.assign(options, {
11+
filepath: file,
12+
})
13+
);
14+
15+
if (output !== input) {
16+
onWriteFile && onWriteFile(file);
17+
writeFileSync(file, output);
18+
}
19+
}
20+
};

src/index.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { relative } from 'path';
2+
3+
import scms from './scms';
4+
import formatFiles from './formatFiles';
5+
import createIgnorer from './createIgnorer';
6+
import isSupportedExtension from './isSupportedExtension';
7+
8+
export default (
9+
directory,
10+
{ since, config, onFoundSinceRevision, onFoundChangedFiles, onWriteFile }
11+
) => {
12+
const scm = scms(directory);
13+
if (!scm) {
14+
throw new Error('Unable to detect a source control manager.');
15+
}
16+
17+
const revision = since || scm.getSinceRevision(directory);
18+
19+
onFoundSinceRevision && onFoundSinceRevision(scm.name, revision);
20+
21+
const changedFiles = scm
22+
.getChangedFiles(directory, revision)
23+
.map(file => relative(directory, file))
24+
.filter(isSupportedExtension)
25+
.filter(createIgnorer(directory));
26+
27+
onFoundChangedFiles && onFoundChangedFiles(changedFiles);
28+
29+
formatFiles(changedFiles, { config, onWriteFile });
30+
};

src/isSupportedExtension.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { extname } from 'path';
2+
import { getSupportInfo } from 'prettier';
3+
4+
const extensions = getSupportInfo().languages.reduce(
5+
(prev, language) => prev.concat(language.extensions || []),
6+
[]
7+
);
8+
9+
export default file => extensions.includes(extname(file));

src/scms/git.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { statSync } from 'fs';
2+
import { join } from 'path';
3+
import execa from 'execa';
4+
5+
export const name = 'git';
6+
7+
export const detect = directory => {
8+
try {
9+
return statSync(join(directory, '.git')).isDirectory();
10+
} catch (error) {
11+
return false;
12+
}
13+
};
14+
15+
const runGit = (directory, args) =>
16+
execa.sync('git', args, {
17+
cwd: directory,
18+
});
19+
20+
const getLines = execaResult => execaResult.stdout.split('\n');
21+
22+
export const getSinceRevision = directory => {
23+
return runGit(directory, ['merge-base', 'HEAD', 'master']).stdout.trim();
24+
};
25+
26+
export const getChangedFiles = (directory, revision) => {
27+
return [
28+
...getLines(
29+
runGit(directory, [
30+
'diff',
31+
'--name-only',
32+
'--diff-filter=ACMRTUB',
33+
revision,
34+
])
35+
),
36+
...getLines(
37+
runGit(directory, ['ls-files', '--others', '--exclude-standard'])
38+
),
39+
].filter(Boolean);
40+
};

src/scms/index.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import * as gitScm from './git';
2+
3+
const scms = [gitScm];
4+
5+
export default directory => {
6+
for (const scm of scms) {
7+
if (scm.detect(directory)) {
8+
return scm;
9+
}
10+
}
11+
};

0 commit comments

Comments
 (0)