diff --git a/README.md b/README.md index 98c928bcba..cca52db644 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ This document is not intended to: * Give advice on design patterns and project architecture * Guide the reader in learning JavaScript -[ESLint Config for the Nerdery JavaScript Standards](https://github.com/thenerdery/javascript-standards/linters) +[ESLint Config for the Nerdery JavaScript Standards](https://github.com/thenerdery/javascript-standards/tree/master/linters) ## Table of Contents diff --git a/linters/tslint.json b/linters/tslint.json new file mode 100644 index 0000000000..ef1e3c94bc --- /dev/null +++ b/linters/tslint.json @@ -0,0 +1,161 @@ +{ + "extends": ["tslint-eslint-rules"], + "rules": { + + // RECOMMENDATIONS + + "interface-name": [true, "never-prefix"], // Require interface names to not have an ā€œIā€ prefix + "deprecation": true, // Warn when deprecated APIs are used + "member-ordering": [ // Enforce member ordering + true, + { + "order": "fields-first" + } + ], + + // MODULES + + "no-duplicate-imports": true, // Disallow duplicate imports + + // ARROW FUNCTIONS + + "prefer-arrow-callback": 2, // Require arrow functions as callbacks + "arrow-spacing": [2, { // Require space before/after arrows + "before": true, + "after": true + }], + + // VARIABLES + + "variable-name": [ // Check variable names for various errors + true, + "ban-keywords", + "check-format", + "allow-leading-underscore", + "allow-pascal-case" + ], + "one-variable-per-declaration": true, // Disallow multiple variable definitions in the same declaration statement + "no-duplicate-variable": [ // Disallow duplicate variable declarations in the same block scope, including parameters + true, + "check-parameters" + ], + "no-unused-expression": true, // Disallow unused expression statements + "no-shadowed-variable": true, // Disallow shadowing variable declarations + "no-unused-variable": true, // Disallow unused imports, variables, functions and private class members + "no-use-before-declare": true, // Disallow usage of variables before their declaration + "no-var-keyword": true, // Disallow usage of the var keyword + "prefer-const": true, // Require const when not reassigned + + // OBJECTS + + "object-literal-shorthand": true, // Enforce use of ES6 object literal shorthand + + // TYPES + + "typedef": [ // Require type definitions to exist + true, + "parameter", + "property-declaration" + ], + "typedef-whitespace": [ // Enforce one space after type information + true, + { + "call-signature": "nospace", + "index-signature": "nospace", + "parameter": "nospace", + "property-declaration": "nospace", + "variable-declaration": "nospace" + } + ], + "no-any": true, // Disallow usage of any as a type declaration + "ban-types": [ // Disallow use of Object and String types + true, + ["Object"], + ["Boolean"], + ["String"], + ["Function"] + ], + "no-extra-boolean-cast": true, // Prevent unnecessary boolean cast + "no-invalid-regexp": true, // Disallow invalid regular expression strings in the RegExp constructor + "no-construct": true, // Disallow String/Number/Boolean constructors + "radix": true, // Require the radix parameter to be specified when calling parseInt + "no-bitwise": true, // Disallow bitwise operators + + // STRINGS + + "no-eval": true, // Disallow eval function invocations + "quotemark": [true, "single", "jsx-double"], // Prefer single quotes for strings + + // BLOCKS + + "forin": true, // Require a for ... in statement to be filtered with an if statement + "curly": [true, "ignore-same-line"], // Enforce braces for if/for/do/while statements + + // COMPARISON + + "no-duplicate-switch-case": true, // Prevent duplicate cases in switch statements + "no-conditional-assignment": true, // Disallow assignment within conditionals + "cyclomatic-complexity": [true, 8], // Enforce a threshold of cyclomatic complexity + "no-switch-case-fall-through": true, // Disallow falling through case statements + "triple-equals": [true, "allow-null-check"], // Require === and !==, allow null check + + // WHITESPACE + + "no-multi-spaces": [true], // Disallow multiple spaces + "whitespace": [ // Enforce whitespace style conventions + true, + "check-branch", + "check-decl", + "check-module", + "check-operator", + "check-separator", + "check-rest-spread", + "check-type", + "check-typecast", + "check-type-operator", + "check-preblock" + ], + "object-curly-spacing": [2, "always"], // Require spaces inside object curly braces + "indent": [true, "spaces", 4], // Enforce 4 spaces + "no-irregular-whitespace": true, // Disallow irregular whitespace + "no-trailing-whitespace": true, // Disallow trailing whitespace at the end of a line + "array-bracket-spacing": [2, "never"], // Disallow spaces inside of brackets + "eofline": true, // Require file to end with a newline + "max-line-length": [ // Disallow lines over 100 characters + true, + { + "limit": 100, + "ignore-pattern": "^import " + } + ], + + // SEMICOLONS + + "semicolon": [true, "always"], // Require semicolons + "no-extra-semi": true, // Disallow extra semicolons + + // COMMENTS + + "jsdoc-format": true, // Enforce basic format rules for JSDoc comments + "valid-jsdoc": [2, { // Require docblocks match params/return type + "requireParamDescription": false, + "requireReturnDescription": false, + "requireReturn": false + }], + "comment-format": [ // Require a space before comment + true, + "check-space" + ], + + // COMMAS + + "trailing-comma": [ // Require trailing commas + true, + { + "multiline": "always", + "singleline": "never" + } + ] + + } +} \ No newline at end of file diff --git a/packages/eslint-config-nerdery-base/.eslintrc.js b/packages/eslint-config-nerdery-base/.eslintrc.js new file mode 100644 index 0000000000..fa43cdb003 --- /dev/null +++ b/packages/eslint-config-nerdery-base/.eslintrc.js @@ -0,0 +1,61 @@ +module.exports = { + rules: { + 'max-params': [2, 5], // Disallow more than 5 parameters + 'no-implicit-coercion': 2, // Disallow type conversion with shorter notations + 'class-methods-use-this': 0, // Allow class instance methods that don't use `this` to prevent unnecessary refactors + 'arrow-body-style': 0, // Disabled. Just because you *can* make something a one-liner, doesn't mean you should. + 'prefer-destructuring': ['error', { // Only prefer destructuring for `const { a } = obj;` (instead of `const a = obj.a`). Arrays and reassignments are left up to developer discretion. + VariableDeclarator: { + array: false, + object: true, + }, + AssignmentExpression: { + array: false, + object: false, + }, + }, { + enforceForRenamedProperties: false, + }], + 'no-continue': 0, // Allow continues. They can be used like an early return to increase readability. + 'no-plusplus': 0, // Allow ++ and --. The rationale for using this rule is that the operators are susceptible to automatic semicolon insertion issues, but that's an unlikely problem to run into. + 'object-curly-newline': 0, // Disabled to leave up to developer discretion + 'vars-on-top': 0, // Disabled because vars are disallowed so this check is superfluous + 'arrow-parens': [2, 'as-needed'], // Require parens in arrow function arguments + 'camelcase': [2, { properties: 'always' }], // Require camelCase property names + 'newline-per-chained-call': [2, { // Require newline per chained method call + ignoreChainWithDepth: 2, + }], + 'spaced-comment': ['error', 'always', { // Require whitespace before comments + line: { + markers: ['/'], + exceptions: ['-'], + }, + block: { + markers: ['/', '*'], + }, + }], + curly: 2, // Require curly brace conventions + 'dot-notation': [2, { // Require dot notation + allowPattern: '^[a-z]+(_[a-z]+)+$', + }], + 'array-bracket-newline': 0, // Leave up to developer discretion + 'array-element-newline': 0, // Leave up to developer discretion + 'function-call-argument-newline': 0, // Leave up to developer discretion + 'max-depth': [1, 4], // Warn when blocks are nested too deeply + 'max-lines': [1, 500], // Warn when files become too long + 'complexity': [1, 20], // Warn when code becomes too complex + 'no-implicit-coercion': 2, // Disallow shorthand type conversions + + 'import/prefer-default-export': 0, // Allow single named exports to prevent unnecessary refactors + 'import/no-default-export': 2, // Mixing default and named exports is unnecessary and can be confusing. This is a contentious topic though. Feel free to override this in your own config. + 'import/dynamic-import-chunkname': 2, // If you're not using webpack or don't care about dynamically imported modules' filenames, feel free to disable this + + // By default, we enforce sorting imports to simplify git history and make it easier when scanning for a specific import. + // It shouldn't cause too much trouble since it's auto-fixable, but if you find this to be more trouble than it's worth, feel free to disable these. + 'import/order': ['error', { alphabetize: { order: 'asc' } }], + 'sort-imports': ['error', { + ignoreDeclarationSort: true, // handled by import/order + ignoreMemberSort: false, + }], + }, +}; diff --git a/packages/eslint-config-nerdery-base/package.json b/packages/eslint-config-nerdery-base/package.json new file mode 100644 index 0000000000..bc42f28cda --- /dev/null +++ b/packages/eslint-config-nerdery-base/package.json @@ -0,0 +1,8 @@ +{ + "name": "eslint-config-nerdery-base", + "version": "1.0.0", + "description": "Nerdery's base JS ESLint config", + "main": ".eslintrc.js", + "author": "Nerdery", + "license": "MIT" +}