From da1b2caaafbc27e2a6a3fa97c186481a3577bd01 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Thu, 25 Feb 2021 19:01:01 -0500 Subject: [PATCH] style: eslint + husky + commitlint --- .eslint | 115 +++++++++++++++++++++++++++++++++++++++++++ commitlint.config.js | 26 ++++++++++ package.json | 26 +++++++++- 3 files changed, 166 insertions(+), 1 deletion(-) create mode 100644 .eslint create mode 100644 commitlint.config.js diff --git a/.eslint b/.eslint new file mode 100644 index 0000000..5b76051 --- /dev/null +++ b/.eslint @@ -0,0 +1,115 @@ +{ + "extends": "airbnb-base", + "parserOptions": { + "sourceType": "script" + }, + + "rules": { + // === Configure rules for our style === + // imports must be resolvable + "import/no-unresolved": "error", + // use single quotes, + // unless a different style allows avoiding escapes + "quotes": ["error", "single", { + "avoidEscape": true, + "allowTemplateLiterals": true + }], + // allow else-if return + "no-else-return": [ "error", { "allowElseIf": true } ], + // expressions split over multiple lines + // should break after the operator + "operator-linebreak": [ "error", "after" ], + // require arrow parens only when needed + // and whenever the body is a block + "arrow-parens": ["error", "as-needed", { "requireForBlockBody": true }], + // what variables are errors in callbacks + "handle-callback-err": [ "error","^(e$|(e|(.*(_e|E)))rr)" ], + // allow dangling commas in functions + // require them everywhere else + "comma-dangle": ["error", { + "arrays": "always-multiline", + "objects": "always-multiline", + "imports": "always-multiline", + "exports": "always-multiline", + "functions": "only-multiline" + }], + // we actually encourage `return await` + "no-return-await": "off", + // allow `while (true)` + "no-constant-condition": ["error", { "checkLoops": false }], + // allow ignoring an error with `catch` + "no-empty": ["error", { "allowEmptyCatch": true }], + // allow `3 + 5 - 1`, but not `3 * 5 - 1` + "no-mixed-operators": ["error", { "allowSamePrecedence": true }], + // require `'use strict';` + "strict": ["error", "global"], + // we actually use tabs for indentation + "indent": ["error", "tab", { "SwitchCase": 1 }], + "no-tabs": "off", + // we want `== null` to also handle undefined + "no-eq-null": "off", + // allow `for (..; i++)` + "no-plusplus": ["error", { "allowForLoopAfterthoughts": true }], + // allow using functions defined later + "no-use-before-define": ["error", "nofunc"], + // require consistent newlines before and after braces + // if contents are multiline + "object-curly-newline": ["error", { "consistent": true, "multiline": true }], + // require consistent linebreaks inline function parenthesis (arguments or params) + "function-paren-newline": ["error", "consistent"], + // only require const if all parts of destructuring can be const + "prefer-const": ["error", { "destructuring": "all" }], + // don't require destructuring for arrays or assignment + "prefer-destructuring": ["error", { + "VariableDeclarator": { "array": false, "object": true }, + "AssignmentExpression": { "array": false, "object": false } + }], + // identical to airbnb rule, except for allowing for..of, because we want to use it + "no-restricted-syntax": [ + "error", + { + "selector": "ForInStatement", + "message": "for..in loops iterate over the entire prototype chain, which is virtually never what you want. Use Object.{keys,values,entries}, and iterate over the resulting array." + }, + { + "selector": "LabeledStatement", + "message": "Labels are a form of GOTO; using them makes code confusing and hard to maintain and understand." + }, + { + "selector": "WithStatement", + "message": "`with` is disallowed in strict mode because it makes code impossible to predict and optimize." + } + ], + // allow lines of up to 120 characters + "max-len": ["error", { "code": 120, "tabWidth": 2, "ignoreUrls": true, "ignoreStrings": true, "ignoreTemplateLiterals": true, "ignoreRegExpLiterals": true }], + + // === Disable rules === + // more liberal naming + "camelcase": "off", + "no-underscore-dangle": "off", + // don't require anonymous function names + "func-names": "off", + // allow console + "no-console": "off", + // allow new for side effects + // allow new with non-capitalized + "no-new": "off", + "new-cap": "off", + // allow shadowing variables (usually callbacks) + "no-shadow": "off", + // allow multiple empty lines in a row + "no-multiple-empty-lines": "off", + // allow not using object shorthand + "object-shorthand": "off", + + // TODO + "consistent-return": "off", + "no-restricted-globals": "off", + "no-prototype-builtins": "off", + "import/no-extraneous-dependencies": "off", + "import/no-dynamic-require": "off", + "global-require": "off", + "no-param-reassign": "off", + "default-case": "off" + } +} \ No newline at end of file diff --git a/commitlint.config.js b/commitlint.config.js new file mode 100644 index 0000000..062d24b --- /dev/null +++ b/commitlint.config.js @@ -0,0 +1,26 @@ +'use strict'; + +module.exports = { + extends: ['@commitlint/config-angular'], + rules: { + 'header-max-length': [1, 'always', 72], + 'type-enum': [ + 2, + 'always', + [ + 'breaking', + 'build', + 'chore', + 'ci', + 'docs', + 'feat', + 'fix', + 'perf', + 'refactor', + 'revert', + 'style', + 'test', + ], + ], + }, +}; diff --git a/package.json b/package.json index eb4557c..19c5285 100644 --- a/package.json +++ b/package.json @@ -4,5 +4,29 @@ "description": "Enter a description here", "main": "theme.less", "keywords": [], - "license": "MIT" + "license": "MIT", + "husky": { + "hooks": { + "pre-commit": "npx lint-staged", + "commit-msg": "npx commitlint -E HUSKY_GIT_PARAMS" + } + }, + "lint-staged": { + "*.js": [ + "eslint --fix", + "git add" + ] + }, + "dependencies": { + "bent": "^7.3.12" + }, + "devDependencies": { + "@commitlint/cli": "11.0.0", + "@commitlint/config-angular": "11.0.0", + "eslint": "7.18.0", + "eslint-config-airbnb-base": "14.2.1", + "eslint-plugin-import": "2.22.1", + "husky": "5.0.9", + "lint-staged": "10.5.4" + } }