Skip to content

Commit

Permalink
feat: do the thing
Browse files Browse the repository at this point in the history
  • Loading branch information
azz committed Jan 7, 2018
1 parent 9940b19 commit 959e814
Show file tree
Hide file tree
Showing 16 changed files with 3,788 additions and 4 deletions.
3 changes: 3 additions & 0 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"presets": [["env", { "targets": { "node": "6.10" } }]]
}
13 changes: 13 additions & 0 deletions .eslintrc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
extends:
- eslint:recommended
- plugin:jest/recommended
- plugin:prettier/recommended
env:
es6: true
node: true
rules:
no-console: off
overrides:
- files: "src/**/*.js"
parserOptions:
sourceType: module
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
node_modules
*.log
dist
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package.json
2 changes: 2 additions & 0 deletions .prettierrc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
trailingComma: es5
singleQuote: true
36 changes: 36 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,39 @@
# `pretty-quick`

> Get Pretty Quick
Runs [Prettier](https://prettier.io) on your changed files.

Supported source control managers:

* Git
* _Add more_

## Install

With `yarn`:

```shellsession
yarn add --dev pretty-quick
```

With `npm`:

```shellsession
npm install --save-dev pretty-quick
```

## Usage

With `yarn`:

```shellsession
yarn pretty-quick
```

With `npm`:

1. Add `"pretty-quick": "pretty-quick"` to the scripts section of `package.json`.
2. ```shellsession
npm run pretty-quick
```
30 changes: 28 additions & 2 deletions bin/pretty-quick.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,35 @@
#!/usr/bin/env node

"use strict";
'use strict';

const prettier = require('prettier');
const chalk = require('chalk');
const mri = require('mri');

const prettyQuick = require('..').default;

const args = mri(process.argv.slice(2));

prettyQuick(
process.cwd(),
Object.assign({}, args, {
onFoundSinceRevision: (scm, revision) => {
console.log(
`🔍 Finding changed files since ${chalk.bold(
scm
)} revision ${chalk.bold(revision)}`
);
},
onFoundChangedFiles: changedFiles => {
console.log(
`🎯 Found ${changedFiles.length} ${
changedFiles.length === 1 ? 'file' : 'files'
} changed.`
);
},
onWriteFile: file => {
console.log(`✍️ Fixing up ${chalk.bold(file)}.`);
},
})
);

console.log('✅ Everything is awesome!');
26 changes: 25 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,36 @@
"description": "Get Pretty Quick",
"repository": "azz/pretty-quick",
"author": "Lucas Azzola <@azz>",
"main": "./dist",
"bin": "./bin/pretty-quick",
"license": "MIT",
"files": [
"bin",
"dist"
],
"dependencies": {
"chalk": "^2.3.0",
"execa": "^0.8.0",
"ignore": "^3.3.7",
"mri": "^1.1.0"
},
"scripts": {
"prepublishOnly": "yarn build",
"build": "babel src -d dist --copy-files",
"test": "jest"
},
"peerDependencies": {
"prettier": "^1.9.2"
"prettier": ">=1.8.0"
},
"devDependencies": {
"babel-cli": "^6.26.0",
"babel-core": "^6.26.0",
"babel-preset-env": "^1.6.1",
"eslint": "^4.15.0",
"eslint-config-prettier": "^2.9.0",
"eslint-plugin-jest": "^21.5.0",
"eslint-plugin-prettier": "^2.4.0",
"jest": "^22.0.4",
"prettier": "1.9.2"
}
}
Empty file.
15 changes: 15 additions & 0 deletions src/createIgnorer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { existsSync, readFileSync } from 'fs';
import { join } from 'path';
import ignore from 'ignore';

export default (directory, filename = '.prettierignore') => {
const file = join(directory, filename);
if (existsSync(file)) {
const text = readFileSync(file, 'utf8');
return ignore()
.add(text)
.createFilter();
}

return () => true;
};
20 changes: 20 additions & 0 deletions src/formatFiles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { readFileSync, writeFileSync } from 'fs';
import { resolveConfig, format } from 'prettier';

export default (files, { config, onWriteFile }) => {
for (const file of files) {
const options = resolveConfig.sync(file, { config });

This comment has been minimized.

Copy link
@montogeek

montogeek Jan 18, 2018

When would it return a different config file?

This comment has been minimized.

Copy link
@azz

azz Jan 18, 2018

Author Member

If there are multiple, e.g:

tools/
  file.js
  .prettierrc
index.js
.prettierrc

files.js will have different config to index.js

This comment has been minimized.

Copy link
@montogeek

montogeek Jan 18, 2018

I searched, couldn't find anything, does prettier CLI supports it?
nvm, it uses cosmicconfig (https://github.com/prettier/prettier/blob/master/src/config/resolve-config.js#L11), it is supported.

This comment has been minimized.

Copy link
@azz

azz Jan 18, 2018

Author Member

It does. The code for it is in https://github.com/davidtheclark/cosmiconfig

const input = readFileSync(file, 'utf8');
const output = format(
input,
Object.assign(options, {
filepath: file,
})
);

if (output !== input) {
onWriteFile && onWriteFile(file);
writeFileSync(file, output);
}
}
};
30 changes: 30 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { relative } from 'path';

import scms from './scms';
import formatFiles from './formatFiles';
import createIgnorer from './createIgnorer';
import isSupportedExtension from './isSupportedExtension';

export default (
directory,
{ since, config, onFoundSinceRevision, onFoundChangedFiles, onWriteFile }
) => {
const scm = scms(directory);
if (!scm) {
throw new Error('Unable to detect a source control manager.');
}

const revision = since || scm.getSinceRevision(directory);

onFoundSinceRevision && onFoundSinceRevision(scm.name, revision);

const changedFiles = scm
.getChangedFiles(directory, revision)
.map(file => relative(directory, file))
.filter(isSupportedExtension)
.filter(createIgnorer(directory));

onFoundChangedFiles && onFoundChangedFiles(changedFiles);

formatFiles(changedFiles, { config, onWriteFile });
};
9 changes: 9 additions & 0 deletions src/isSupportedExtension.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { extname } from 'path';
import { getSupportInfo } from 'prettier';

const extensions = getSupportInfo().languages.reduce(
(prev, language) => prev.concat(language.extensions || []),
[]
);

export default file => extensions.includes(extname(file));
40 changes: 40 additions & 0 deletions src/scms/git.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { statSync } from 'fs';
import { join } from 'path';
import execa from 'execa';

export const name = 'git';

export const detect = directory => {
try {
return statSync(join(directory, '.git')).isDirectory();
} catch (error) {
return false;
}
};

const runGit = (directory, args) =>
execa.sync('git', args, {
cwd: directory,
});

const getLines = execaResult => execaResult.stdout.split('\n');

export const getSinceRevision = directory => {
return runGit(directory, ['merge-base', 'HEAD', 'master']).stdout.trim();
};

export const getChangedFiles = (directory, revision) => {
return [
...getLines(
runGit(directory, [
'diff',
'--name-only',
'--diff-filter=ACMRTUB',
revision,
])
),
...getLines(
runGit(directory, ['ls-files', '--others', '--exclude-standard'])
),
].filter(Boolean);
};
11 changes: 11 additions & 0 deletions src/scms/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import * as gitScm from './git';

const scms = [gitScm];

export default directory => {
for (const scm of scms) {
if (scm.detect(directory)) {
return scm;
}
}
};

0 comments on commit 959e814

Please sign in to comment.