Linters
# Linters
# Introduction
Using linters can help us writing better code. We've chosen Husky to execute linters on the stage files.
# Husky and lint-staged
Modern native Git hooks made easy Husky supports al native git hookes https://git-scm.com/docs/githooks (opens new window)
# Install
npm install husky lint-staged --save-dev
# Configuration
Add hooks to package.json
"husky": {
"hooks": {
"pre-commit": "lint-staged",
"pre-push": "php artisan test"
}
},
Create a configuration file lint-staged.config.js
In this example we have added a pre-commit hook for checking php files
module.exports = {
'**/*.php': ['php ./vendor/bin/php-cs-fixer fix --config .php-cs-fixer-config.php --allow-risky=yes'],
};
# Install pre-commit hooks
Run below command to install
npx husky install
# Trouble shooting
In my first project everything workt fine, my second the hooks were not firing. beneath the solution to solve this:
npm install -D husky
npm set-script prepare "husky install" && npm run prepare
npx husky add .husky/pre-commit "npx lint-staged"
git commit -m "added husky and lint-stagged" // here you will notice the lint-staged checking the files with help of husky
# PHP CS Fixer
# install
composer require friendsofphp/php-cs-fixer
# Configuration
Create a configuration file .php-cs-fixer-config.php:
<?php
use PhpCsFixer\Config;
use PhpCsFixer\Finder;
$finder = Finder::create()
->in(__DIR__)
->exclude(['bootstrap', 'storage', 'vendor'])
->name('*.php')
->name('_ide_helper')
->notName('*.blade.php')
->ignoreDotFiles(true)
->ignoreVCS(true);
return (new Config())
->setRules([
'@PSR12' => true,
'ordered_imports' => ['imports_order' => ['class', 'function', 'const'], 'sort_algorithm' => 'alpha'],
])
->setFinder($finder);
# ESLint
# Install
npm install eslint --save-dev
# Config
Running below code wil generate a config file.
npm init @eslint/config
Config file
module.exports = {
'env': {
'browser': true,
'es2021': true,
},
'extends': [
'eslint:recommended',
'plugin:vue/recommended',
],
'parserOptions': {
'parser': 'babel-eslint',
'ecmaVersion': 6,
},
'plugins': [
'vue',
],
'rules': {
'indent': [
'error',
2,
{
'SwitchCase': 1,
},
],
'linebreak-style': [
'error',
'unix',
],
'quotes': [
'error',
'single',
],
'semi': [
'error',
'always',
],
'prefer-const': ['error', {
'destructuring': 'any',
'ignoreReadBeforeAssign': false,
}],
'key-spacing': ['error', {
'afterColon': true,
}],
'object-curly-spacing': ['error', 'always'],
'comma-dangle': ['error', 'always-multiline'],
'eol-last': ['error', 'always'],
'nonblock-statement-body-position': ['error', 'below'],
'vue/html-closing-bracket-newline': 'error',
'vue/html-closing-bracket-spacing': 'error',
'vue/prop-name-casing': 'error',
'vue/max-attributes-per-line': ['error', {
'singleline': 1,
'multiline': 1,
}],
'vue/multi-word-component-names': 0,
},
'globals': {
'module': false,
'process': false,
'require': false,
'Config': false,
'Echo': false,
'$': false,
'Nova': false,
'__dirname': false,
},
overrides: [
{
files: [
'webpack.mix.js',
'ThemePlugin.js',
'_templates/**',
'docs/.vuepress/**',
],
env: { node: true },
},
{
files: ['nova-components/**/*'],
globals: {
Nova: false,
},
},
],
};
# Unit Testing
Unit testing can be enforced using a pre-push hook to your package.json
"husky": {
"hooks": {
"pre-push": "php artisan test"
}
},
# PHP Insights
The perfect starting point to analyze the code quality of your PHP projects
# Install
composer require nunomaduro/phpinsights --dev
# Execute
PHP insights can analyse and fix your php code
php artisan insights path/to/analyse --fix
# The Full Monty
# package json
{
"private": true,
"scripts": {
"dev": "npm run development",
"development": "mix",
"watch": "mix watch",
"watch-poll": "mix watch -- --watch-options-poll=1000",
"hot": "mix watch --hot",
"prod": "npm run production",
"production": "mix --production",
"prepare": "husky install"
},
"devDependencies": {
"axios": "^0.25",
"browser-sync": "^2.27.9",
"browser-sync-webpack-plugin": "^2.3.0",
"eslint": "^8.15.0",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-config-prettier": "^8.5.0",
"eslint-config-standard": "^17.0.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-n": "^15.2.0",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-promise": "^6.0.0",
"eslint-plugin-vue": "^8.7.1",
"husky": "^8.0.1",
"laravel-mix": "^6.0.6",
"lint-staged": "^12.4.1",
"lodash": "^4.17.19",
"postcss": "^8.4.14",
"postcss-html": "^1.4.1",
"prettier": "^2.6.2",
"sass": "^1.51.0",
"sass-loader": "^12.6.0",
"stylelint": "^14.8.5",
"stylelint-config-prettier": "^9.0.3",
"stylelint-config-sass-guidelines": "^9.0.1",
"stylelint-config-standard-scss": "^3.0.0",
"stylelint-config-standard-vue": "^1.0.0",
"stylelint-prettier": "^2.0.0",
"vue-loader": "^17.0.0"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged",
"pre-push": "php artisan test"
}
},
"dependencies": {
"bootstrap": "^5.1.3",
"eslint-config-airbnb": "^19.0.4",
"stylelint-scss": "^4.2.0",
"video.js": "^7.19.2",
"vue": "^3.2.33"
}
}
###lint staged
module.exports = {
'**/*.php': ['php ./vendor/bin/php-cs-fixer fix --config .php-cs-fixer-config.php --allow-risky=yes'],
'**/*.php': ['php artisan insights -v'],
"**/*{js,ts}": "eslint --fix",
"**/*{vue,htm,html,css,sss,less,scss,sass}": "stylelint --fix"
};