Code style?
Why, in the world,
do I need
this?
— Not that it is necessary.
While you work alone.
— But as soon as the team begins to grow …
… and more …
… and even more …
… and more …
… and …
… and at some point it becomes obvious
that you need rules.
— We need cover scripts, styles and flow
How
should
I choose
code style?
It should be maintained by
someone else
— Because we don't want to build a better world, we want to build an app, get our money, then buy a rifle and … but where was I?
And
it should be trandy!
— Because it increase your team mates value as developers and thas it would be easier to implement
Anything
else?
No
— It does not metter if you use space or tabs: your text editor can handle any of them. Only thing is matter — code uniformity.
And that's it?
— Yes! Your teammates from Delhi are already running to implement code style you have selected. They struggle for it.
— Actually no, they don't. Nobody want your code style.
I am an artist!
Don't restrict me!
— You need to preset, check, automatize and force code style, otherwise there would be none.
$ vi .editorconfig
[*]
indent_style = space
indent_size = 2
tab_width = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
$ sudo npm i -g eslint
$ npm i -D eslint
$ eslint --init
$ vi .eslintrc
// .eslintrc
{
"extends": "airbnb",
"plugins": [
"react",
"jsx-a11y",
"import"
]
}
$ npm info
"eslint-config-airbnb@latest"
peerDependencies
{ eslint: '^3.19.0 || ^4.3.0',
'eslint-plugin-jsx-a11y': '^5.1.1',
'eslint-plugin-import': '^2.7.0',
'eslint-plugin-react': '^7.1.0' }
$ npm i -D eslint-plugin-react@latest
$ npm i -D eslint-plugin-import@latest
$ npm i -D eslint-plugin-jsx-a11y@latest
$ npm i -D eslint-config-airbnb@latest
// .eslintrc
{
"parser": "babel-eslint",
"extends": "airbnb",
"plugins": [
"react",
"jsx-a11y",
"import"
]
}
// .eslintrc
{
"parser": "babel-eslint",
"extends": "airbnb",
"plugins": [
"react",
"jsx-a11y",
"import"
],
"env": {
"browser": true,
"es6": true,
},
}
$ npm i -D babel-eslint@latest
$ eslint ./source
--color
--format stylish
$ eslint ./source
--color
--format stylish
--fix
// package.json
{ // …
"scripts": {
"lint:js": "eslint ./source
--color
--format stylish
--fix"
}
}
$ npm run lint:js
So,
should I run it after each change?
— To see problems on the fly you should configure your editor
Nice, but
what if i'll ignore linter
errors all together
— Then I should, obviously, use…
Hook
#!/bin/bash
# .git/hooks/pre-commit
if !(npm run lint:js --silent) then
exit 1;
fi
Do you
belive that I will create pre-commit all by
myself?
Am I my own worst enemy? And It's tricky!
You can't store hooks with a repo you know.
$ npm i -D lint-staged
$ npm i -D husky
// package.json
{ // …
"scripts": { // …
"precommit": "lint-staged"
},
"lint-staged": { // …
"*.{js,jsx}": "eslint"
}
}
How much will it leave from my code?
— Nothing!
$ npm i -D -E prettier
// .prettierrc
{
"parser": "babylon",
"useTabs": false,
"tabWidth": 2,
"singleQuote": true,
"semi": true,
"printWidth": 100,
"trailingComma": "all",
"bracketSpacing": true,
"jsxBracketSameLine": true,
"proseWrap": false,
}
// package.json
{
"scripts": {
"format": "prettier
--config .prettierrc
--write 'src/**/*.{js,jsx}'"
},
}
$ npm i -D eslint-plugin-prettier
// .eslintrc
{
"plugins": [
"prettier",
],
"rules": {
"prettier/prettier": "error"
},
}
$ npm i -D eslint-config-prettier
// .eslintrc
{
"extends": [
"airbnb",
"prettier",
"prettier/react"
],
}
▉▉▉▉
What about styles?
$ sudo npm i -g stylelint
$ npm i -D stylelint
$ npm i -D stylelint-config-standard
$ vi .stylelintrc
{
"syntax": "less",
"extends": "stylelint-config-standard",
"rules": {
// …
}
}
stylelint ./src/**/*.less
--syntax less
--color
--formatter verbose
stylelint ./src/**/*.less
--syntax less
--color
--formatter verbose
--fix
// package.json
{ // …
"scripts": {
"lint:less": "stylelint ./src/**/*.less
--syntax less
--color
--formatter verbose
--fix"
}
}
$ npm run lint:less
But you will not use hooks, right?
— I definitely will.
// package.json
{ // …
"scripts": { // …
"precommit": "lint-staged"
},
"lint-staged": { // …
"*.less": "stylelint"
}
}
▉▉▉ ▉▉ ▉
▉▉▉▉▉
▉▉▉▉▉▉▉
What
about flow?
— More hooks…
vi ./hooks/commit-msg
chmod 0755 ./hooks/commit-msg
#!/bin/bash
MESSAGE=`cat "$1"`;
if (![[ "$MESSAGE" =~ ^[A-Z]+-[0-9]+\ -\ .*$ ]])
&& [ "$MESSAGE" != "merge" ];
then
echo "Wrong commit message format.";
exit 1;
fi
if [[ "$MESSAGE" =~ ([а-яА-Я]+) ]]; then
echo "Don't use russian for commit message.";
exit 2;
fi
if (![[ "$MESSAGE" =~ ^[A-Z]+-[0-9]+\ -\ .{5,}$ ]])
&& [ "$MESSAGE" != "merge" ]; then
echo "Commit message is too short,
try to be more descriptive.";
exit 3;
fi
// package.json
{ // …
"scripts": { // …
"commitmsg": "./hooks/commit-msg ${GIT_PARAMS}"
},
// …
}
npm init
npm i -S command-line-args
// index.js
#! /usr/bin/env node
// index.js
#! /usr/bin/env node
const fs = require('fs');
const filePath = process.argv[2];
if (!fs.existsSync(filePath)) {
console.log('Can not read commit message');
process.exit(1);
}
const message = fs.readFileSync(filePath);
const commandLineArgs = require('command-line-args');
const optionDefinitions = [{
name: 'regexp',
alias: 'r',
type: String,
defaultValue: '^[A-Z]+-[0-9]+\s-\s[\W\w\s]{5,}[\s]*$' },
];
const cli = commandLineArgs(optionDefinitions);
const commonRegexp = new RegExp(
cli.regexp,
'ig'
);
if (!commonRegexp.test(message)) {
console.log("Wrong commit message format");
process.exit(3);
}
process.exit(0);
// package.json
"name": "my-message-hook",
"main": "index.js",
"bin": {"commit-msg": "index.js"},
"scripts": {
"release": "npm version patch &&
git push --tags &&
npm publish --access public"
}
npm i -S my-message-hook
// package.json
"scripts": {
"commitmsg": "commit-msg
${GIT_PARAMS}
-r MyRegExp"
},
But are hooks enought?
— No
▉▉▉▉,
whats next?
Just want
to let you know that we made a voodoo doll
of you
Anton Nemtsev
http://silentimp.info/
@silentimp
thesilentimp@gmail.com
skype: ravencry